Is there any solution for this? We need parallel edges, but not that way how ParallelEdgeLayout makes that.
I tried to rewrite the layout function of parallel layout to move the edges, but edges has no usable geometry: x, y, width, height are 0. There I couldn't move them anywhere.
Tried to use setStyle, but did not do anything:
var s = model.getStyle(parallels[i]) + 'entryX='+x0+';exitX='+x0+';'
console.log(s)
model.setStyle(parallels[i], s);
Oh my God! Here is a solution. Not the dream edges, but almost... Maybe there are more beautiful solutions (post one), but this is mine for showing real parallel edges:
var spx = 1 / 22;
var spy = 1 / 8;
var x0 = 0.5;
var y0 = 0.5;
for (var i = 0; i < parallels.length; i++) {
var source = view.getVisibleTerminal(parallels[i], true);
var target = view.getVisibleTerminal(parallels[i], false);
var src = model.getGeometry(source);
var trg = model.getGeometry(target);
var srcx = src.x, srcy = src.y, trgx = trg.x, trgy = trg.y;
if (parallels[i].getParent() != source.getParent()) {
var pGeo = model.getGeometry(source.getParent());
srcx = src.x + pGeo.x;
srcy = src.y + pGeo.y;
}
if (parallels[i].getParent() != target.getParent()) {
var pGeo = model.getGeometry(target.getParent());
trgx = trg.x + pGeo.x;
trgy = trg.y + pGeo.y;
}
var scx = srcx + src.width; // source element right
var scy = srcy + src.height; // source element bottom
var tcx = trgx + trg.width; // target element right
var tcy = trgy + trg.height; // target element bottom
var dx = tcx - scx; // len x
var dy = tcy - scy; // len y
var sourcePointX, sourcePointY, targetPointX, targetPointY;
if (Math.abs(dx) > Math.abs(dy)) { // horizontal
sourcePointY = y0;
targetPointY = y0;
if (srcx < trgx) { // left to right
sourcePointX = 1;
targetPointX = 0;
} else {
sourcePointX = 0;
targetPointX = 1;
}
} else {
sourcePointX = x0;
targetPointX = x0;
if (srcy < trgy) { // top to bottom
sourcePointY = 1;
targetPointY = 0;
} else {
sourcePointY = 0;
targetPointY = 1;
}
}
this.graph.setConnectionConstraint(parallels[i], parallels[i].source, true, new mxConnectionConstraint(new mxPoint(sourcePointX, sourcePointY), true));
this.graph.setConnectionConstraint(parallels[i], parallels[i].target, false, new mxConnectionConstraint(new mxPoint(targetPointX, targetPointY), true));
if (i % 2) {
x0 += spx * (i + 1);
y0 += spy * (i + 1);
} else {
x0 -= spx * (i + 1);
y0 -= spy * (i + 1);
}
}
Related
I am making this background for a page drawing random lines. The lines are being drawn and it looks as it was supposed to but when I look into the console I get about ~10 errors every second. It says it cannot read startX and starY. When I change it to x and why it does not draw the lines anymore.
var sandbox = document.getElementById('sandbox');
ctx = sandbox.getContext('2d');
var referencePoint = function(x, y) {
this.startX = x;
this.startY = y;
};
const progressPoints = [];
for (let i = 0; i < 15; i++) {
let x = Math.floor(Math.random() * sandbox.width);
let y = Math.floor(Math.random() * sandbox.height);
progressPoints.push(new referencePoint(x, y));
};
ctx.strokeStyle= "grey";
ctx.moveTo(progressPoints[0].x, progressPoints[0].y);
It supposedly cannot read those startX and startY:
var counter = 1,
interval = setInterval(function() {
var point = progressPoints[counter];
ctx.lineTo(point.startX, point.startY);
//alert(point.startX, point.startY)
ctx.stroke();
if(counter >= progressPoints.lenght){
clearInterval(interval);
};
counter++
}, 140);
(function() {
var contentBox = $('div.content-box'),
activeContent = contentBox.find('div.active-content'),
pageTransitionOverlay = contentBox.find('div.page-transition-overlay'),
navBtn = $('a.nav-btn'),
hiddenContent = $('div.hidden-content');
navBtn.on('click', function(e) {
var self = $(this),
moveToActive = hiddenContent.find('div.' + self.data('target-class'));
contentBox.addClass('transitionEffect');
pageTransitionOverlay.fadeIn(300, function() {
// Change content
self.closest('div.content-wrapper').appendTo(hiddenContent);
moveToActive.appendTo(activeContent);
// Transition transitionEffect
contentBox.removeClass('transitionEffect');
pageTransitionOverlay.fadeOut(300);
});
e.preventDefault();
});
})();
So it seems that length is too much, try 1 less
if (counter >= progressPoints.length - 1) { ... }
var sandbox = document.getElementById('sandbox');
ctx = sandbox.getContext('2d');
var referencePoint = function(x, y) {
this.startX = x;
this.startY = y;
};
const progressPoints = [];
for (let i = 0; i < 15; i++) {
let x = Math.floor(Math.random() * sandbox.width);
let y = Math.floor(Math.random() * sandbox.height);
progressPoints.push(new referencePoint(x, y));
};
ctx.strokeStyle = "grey";
ctx.moveTo(progressPoints[0].x, progressPoints[0].y);
var counter = 1,
interval = setInterval(function() {
var point = progressPoints[counter];
ctx.lineTo(point.startX, point.startY);
//alert(point.startX, point.startY)
ctx.stroke();
if (counter >= progressPoints.length - 1) {
clearInterval(interval);
};
counter++
}, 140);
(function() {
var contentBox = $('div.content-box'),
activeContent = contentBox.find('div.active-content'),
pageTransitionOverlay = contentBox.find('div.page-transition-overlay'),
navBtn = $('a.nav-btn'),
hiddenContent = $('div.hidden-content');
navBtn.on('click', function(e) {
var self = $(this),
moveToActive = hiddenContent.find('div.' + self.data('target-class'));
contentBox.addClass('transitionEffect');
pageTransitionOverlay.fadeIn(300, function() {
// Change content
self.closest('div.content-wrapper').appendTo(hiddenContent);
moveToActive.appendTo(activeContent);
// Transition transitionEffect
contentBox.removeClass('transitionEffect');
pageTransitionOverlay.fadeOut(300);
});
e.preventDefault();
});
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<canvas id="sandbox"></canvas>
This is a query about something that popped up while I was experimenting with the canvas element via javascript. I wanted to have an array of points that formed a gradient which moved with time, which works perfectly apart from a bizarre pattern that comes up (only after the first wave or more), which also changes according to the number of columns and rows in the canvas (changing the size of the points just makes the patterns bigger or smaller, it's always on the same pixels.
Here's a little demo of what I mean with a bit of interface for you to mess around with, an example of the changing patterns is if the number of rows is changed to 0.75x the number of columns from the original (i.e. 40 columns, 30 rows).
http://codepen.io/zephyr/pen/GpwwWB
Javascript:
String.prototype.hexToRGBA = function(a) {
function cutHex(h) {
return (h.charAt(0) == "#") ? h.substring(1, 7) : h
}
var r = parseInt((cutHex(this)).substring(0, 2), 16);
var g = parseInt((cutHex(this)).substring(2, 4), 16);
var b = parseInt((cutHex(this)).substring(4, 6), 16);
return 'rgba(' + r.toString() + ',' + g.toString() + ',' + b.toString() + ',' + a.toString() + ')';
}
CanvasRenderingContext2D.prototype.clearDrawRect = function(shape) {
this.clearRect(shape.position.x, shape.position.y, shape.size, shape.size);
this.fillStyle = shape.color.base;
this.fillRect(shape.position.x, shape.position.y, shape.size, shape.size);
}
CanvasRenderingContext2D.prototype.render = function(render) {
(function animate() {
requestAnimationFrame(animate);
render();
})();
}
CanvasRenderingContext2D.prototype.renderAndThrottleFpsAt = function(fps, render) {
var fpsInterval, startTime, now, then, elapsed;
fpsInterval = 1000 / fps;
then = Date.now();
startTime = then;
(function animate() {
requestAnimationFrame(animate);
now = Date.now();
elapsed = now - then;
if (elapsed > fpsInterval) {
then = now - (elapsed % fpsInterval);
render();
}
})();
}
CanvasRenderingContext2D.prototype.pool = {};
CanvasRenderingContext2D.prototype.parsePoint = function(x, y, s, c) {
return {
color: c,
position: {
x: x,
y: y
},
size: s
}
}
CanvasRenderingContext2D.prototype.fillPointsPool = function(size, cols, rows, color) {
var i = cols;
var j = rows;
while(i--){
while(j--){
var x = i * size;
var y = j * size;
var a = (i * j) / (cols * rows);
var c = {
hex: color,
alpha: a,
dir: 1
};
if (typeof this.pool.points == 'undefined') {
this.pool.points = [this.parsePoint(x, y, size, c)];
} else {
this.pool.points.push(this.parsePoint(x, y, size, c));
}
}
j = rows;
}
}
CanvasRenderingContext2D.prototype.updatePointsPool = function(size, cols, rows, color) {
this.pool.points = [];
this.clearRect(0,0,this.canvas.width,this.canvas.height);
this.fillPointsPool(size, cols, rows, color);
}
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Populate Points
var size = document.getElementById('size');
var cols = document.getElementById('cols');
var rows = document.getElementById('rows');
var color = document.getElementById('color');
ctx.fillPointsPool(size.value, cols.value, rows.value, color.value);
size.oninput = function(){
ctx.updatePointsPool(this.value, cols.value, rows.value, color.value);
}
cols.oninput = function(){
ctx.updatePointsPool(size.value, this.value, rows.value, color.value);
}
rows.oninput = function(){
ctx.updatePointsPool(size.value, cols.value, this.value, color.value);
}
color.oninput = function(){
ctx.updatePointsPool(size.value, cols.value, rows.value, this.value);
}
ctx.renderAndThrottleFpsAt(60, function(){
var i = 0;
var len = ctx.pool.points.length;
while (i<len) {
var point = ctx.pool.points[i];
// Change alpha for wave
var delta = 0.01;
point.color.alpha = point.color.alpha + (delta * point.color.dir);
if (point.color.alpha > 1) {
point.color.dir = -1;
} else if (point.color.alpha <= 0) {
point.color.dir = 1;
}
// Calculate rgba value with new alpha
point.color.base = point.color.hex.hexToRGBA(point.color.alpha);
ctx.clearDrawRect(point);
i++;
}
});
Do any of you have an idea of what's causing the pattern to appear, and any suggestions on a fix for this?
Note: I will be changing the updatePointsPool function
You are forgetting to clamp your alpha values when you change the direction. The small error in the alpha value accumulates slowly producing the unwanted artifacts you see as the animation progresses.
To fix add the top and bottom limits to alpha in the code just after you add delta direction to alpha.
if (point.color.alpha > 1) {
point.color.alpha = 1; // clamp alpha max
point.color.dir = -1;
} else if (point.color.alpha <= 0) {
point.color.alpha = 0; // clamp alpha min
point.color.dir = 1;
}
I have a scenario in which I am having a canvas, I am dragging some drawing from the left side of the canvas and dropping it on the right side of it and if I am dropping one box near to another one it also clubbing together. Now I need to do two more things -
First, as soon as I am clubbing one with another I want to give this set, of more than one boxes, a treatment of one box. meaning that if I am dragging any one of the box which are clubbed together, whole set of the boxes should be dragged together.
second, as and when I am dropping the boxes I want to generate some plain text based on the box which has been dropped, for example if I dropped "first box", the plain text should be something like "you dropped first box first". And this thing I need to do on the sequence, meaning if the second box is appearing first the text according to that box should appear first.
Here is the code which I have completed
<script type="text/javascript">
window.onload = function(){
draw();
}
</script>
<body style="margin: 0;padding:0;clear:both; cursor: pointer">
<canvas id="canvas" tabindex="1" style="float:left" ></canvas>
<div id="plainEnglish" tabindex="2" style="float: left;"></div>
</body>
<script>
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
c.width = 600;
c.height = 300;
//My mouse coordinates
var x,y;
c.addEventListener("mousedown",down);
c.addEventListener("mousemove",move);
c.addEventListener("mouseup",up);
var r = 0;
function counter() {
r++;
console.log(r);
}
//I'll save my boxes in this array
var myBoxes = new Array();
// Those boxes which I have moved to droppable area of the canvas.
var myDroppedBoxes = new Array();
//This function describes what a box is.
//Each created box gets its own values
function box(x,y,w,h,rgb,text) {
this.x = x,
this.y = y;
this.xS = x; //saving x
this.yS = y; //saving y
this.w = w;
this.h = h;
this.rgb = rgb;
this.text = text;
//to determine if the box is being draged
this.draging = false;
this.isBeingDragged = false;
}
//Let's make some boxes!!
myBoxes[0] = new box(20,20,75,20,"#6AA121","First");
myBoxes[1] = new box(20,50,75,20,"#6AA121", "Second");
myBoxes[2] = new box(20,80,75,20,"#6AA121","third");
//here we draw everything
function draw() {
ctx.clearRect(0,0,c.width,c.height);
//Dropable area
ctx.fillStyle="red";
ctx.fillRect(c.width/2,0,c.width,c.height);
//Boxes!
for (var i = 0; i<myBoxes.length; i++) {
var b = myBoxes[i];
if (b.draging) { //box on the move
//Also draw it on the original spot
ctx.fillStyle=b.rgb;
ctx.fillRect(b.xS,b.yS,b.w,b.h);
ctx.strokeRect(b.xS,b.yS,b.w,b.h);
ctx.font = "14px Arial";
ctx.strokeText(b.text, b.xS + 5 , b.yS + 15);
}
ctx.fillStyle=b.rgb;
ctx.fillRect(b.x,b.y,b.w,b.h);
ctx.strokeRect(b.x,b.y,b.w,b.h);
ctx.font = "14px Arial";
ctx.strokeText(b.text, b.x + 5 , b.y + 15);
}
for(var i = 0; i< myDroppedBoxes.length; i++) {
var b = myDroppedBoxes[i];
ctx.fillStyle=b.rgb;
ctx.fillRect(b.x,b.y,b.w,b.h);
ctx.strokeRect(b.x,b.y,b.w,b.h);
ctx.font = "14px Arial";
ctx.strokeText(b.text, b.x + 5 , b.y + 15);
}
}
function down(event) {
event = event || window.event;
x = event.pageX - c.offsetLeft,
y = event.pageY - c.offsetTop;
for (var i = 0; i<myBoxes.length; i++) {
var b = myBoxes[i];
if (x>b.xS && x<b.xS+b.w && y>b.yS && y<b.yS+b.h) {
myBoxes[i].draging = true;
myBoxes[i].isBeingDragged = true;
}
}
for (var i = 0; i<myDroppedBoxes.length; i++) {
var b = myDroppedBoxes[i];
if (x>b.x && x<b.x + b.w && y>b.y && y<b.y + b.h) {
b.draging = true;
b.isBeingDragged = true;
}
}
draw();
}
function move(event) {
event = event || window.event;
x = event.pageX - c.offsetLeft,
y = event.pageY - c.offsetTop;
for (var i = 0; i<myBoxes.length; i++) {
var b = myBoxes[i];
if (b.draging && b.isBeingDragged) {
myBoxes[i].x = x;
myBoxes[i].y = y;
if (b.x>c.width/2) {
var length = myDroppedBoxes.length ;
myDroppedBoxes[length] = new box(x,y,b.w,b.h,b.rgb,b.text);
myDroppedBoxes[length].draging = true;
myDroppedBoxes[length].isBeingDragged = true;
b.x = b.xS;
b.y = b.yS;
b.isBeingDragged = false;
}
}
}
for (var i = 0; i<myDroppedBoxes.length; i++) {
var b = myDroppedBoxes[i];
if (b.draging && b.isBeingDragged) {
b.x = x;
b.y = y;
}
}
draw();
}
function up(event) {
event = event || window.event;
x = event.pageX - c.offsetLeft,
y = event.pageY - c.offsetTop;
for (var i = 0; i< myBoxes.length; i++) {
var b = myBoxes[i];
if (b.draging && b.isBeingDragged) {
//Let's see if the rectangle is inside the dropable area
if (b.x < c.width/2) {
myBoxes[i].x = b.xS;
myBoxes[i].y = b.yS;
myBoxes[i].draging = false;
b.isBeingDragged = false;
}
}
}
for (var i = 0; i< myDroppedBoxes.length; i++) {
var b = myDroppedBoxes[i];
if ( b.isBeingDragged) {
//Let's see if the rectangle is inside the dropable area
if (b.x>c.width/2) {
b.x = x;
b.y = y;
clubLegos(b);
plainTextMaker();
b.isBeingDragged = false;
}
else {
//No it's not, sending it back to its original spot
myDroppedBoxes.splice(i,1);
}
}
}
draw();
}
function clubLegos(b) {
// this loop is for checking that the box is lying near to which other box.
for(var j = 0; j < myDroppedBoxes.length; j++) {
var z = myDroppedBoxes[j];
if(!z.isBeingDragged) {
if(((x > z.x) && (x < (z.x + z.w))) && ((y > (z.y - 15)) && (y < (z.y + z.h + 10)))) {
b.x = z.x;
if( (y - z.y) >= 0) {
b.y = (z.y + z.h);
console.log("inside if " + y + " " + z.y);
}
else {
console.log("inside else " + y + " " + z.y);
b.y = (z.y - z.h);
}
}
}
}
}
function plainTextMaker() {
plainEnglishDiv = document.getElementById("plainEnglish");
plainEnglishDiv.innerHTML = "<h3>Here I am generating some plain text based on each drag and drop</h3>";
}
</script>
</html>
Here is the JS Fiddle for the same -
http://jsfiddle.net/akki166786/wa52f9pm/
Any help is greatly appreciated.
Thanks in advance.
Give each of your box objects something similar to Html's class.
This way you can drag every box with the same "class" simultaneously.
Add a club: property to each box.
// at top of app set a counter to make new clubs
var nextClub=0;
// each new box gets a unique "club"
function box(x,y,w,h,rgb,text) {
...
club:(nextClub++),
...
In clubLegos(b) when you're attaching dragged box b to another box z, also give the dropped box (b) & any member of (z)'s group a brand new club id:
// give the dropped box (b) & any member of (z)'s group a brand new club id
...if attaching b to z
b.club=nextClub;
for(var i=0;i<myBoxes.length;i++){
var bb=myBoxes[i];
if(bb.club==z.club){
bb.club=nextClub;
}
}
nextClub++;
This way, for example, if the mousedown has the user starting to drag a box with club==2, then you can add each myBoxes with club==2 into your dragging array and every box with club==2 will be dragged simultaneously.
I need to create an animation of dropping box, which supposed to bounce 10 times when it reaches a certain Y point on canvas, each time twice lower that the previous. So I have the animation of the dropping box, but I can't make the bounce work. Here are the functions that I wrote:
function dropBox(y, width, height) {
var img_box = new Image();
img_box.src = 'images/gift_box_small.png';
var box_y_pos = y;
if(y==0)
box_y_pos = y-img_box.naturalHeight;
img_box.onload = function(){
ctx_overlay.save();
ctx_overlay.clearRect(0,0,width,height);
ctx_overlay.drawImage(img_box, (width/2)-(img_box.naturalWidth/2), box_y_pos);
ctx_overlay.restore();
}
box_y_pos += 3;
var box_bottom_position = box_y_pos - img_box.naturalHeight;
if(box_y_pos+img_box.naturalHeight<height-25)
var loopTimer = setTimeout(function() {dropBox(box_y_pos, width, height)},24);
else
bounceBox(img_box, box_y_pos, box_y_pos, (height/2)-(img_box.naturalHeight/2), "up");
}
function bounceBox(img, img_final_pos, y, midway_pos, direction){
var midway = midway_pos;
var direction = direction;
var img_y_pos = y;
img.onload = function(){
ctx_overlay.save();
ctx_overlay.clearRect(0,0,docWidth,docHeight);
ctx_overlay.drawImage(img, (docWidth/2)-(img.naturalWidth/2), img_y_pos);
ctx_overlay.restore();
}
for(var i = 0; i < 10; i++){
if(direction=="up"){
//going up
if(img_y_pos>midway_){
img_y_pos -= 3;
var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "up")},24);
} else {
img_y_pos += 3;
midway = Math.floor(midway /= 2);
if(midway%2>0)
midway += 1;
var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "down")},24);
}
} else {
//going down
if(img_y_pos < img_final_pos){
img_y_pos += 3;
var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "down")},24);
}
}
}
}
JSFiddle: http://jsfiddle.net/n2derqgw/3/
Why isn't it working and how can I make it work?
To avoid getting a headache, you've better handle the animation within a single function called with a setInterval.
And keep all animation-related data in one object.
So the code below does not exactly what you want, but should get you started :
http://jsfiddle.net/n2derqgw/4/
Setup :
var canvas_overlay, ctx_overlay, docWidth, docHeight;
var img_box = new Image();
img_box.src = 'http://corkeynet.com/test/images/gift_box_small.png';
var mustBeReadyCount = 2; // must load image and window
img_box.onload = launchWhenReady;
window.onload = launchWhenReady;
var animationStep = '';
var boxAnimationData = {
animationStep: '',
y: 0,
maxY: 0,
bounceCount: 6,
direction: -1,
bounceHeight: 0
};
function launchWhenReady() {
mustBeReadyCount--;
if (mustBeReadyCount) return;
docWidth = window.innerWidth;
docHeight = window.innerHeight;
canvas_overlay = document.getElementById('canvas_overlay');
ctx_overlay = canvas_overlay.getContext('2d');
resizeCanvas(docWidth, docHeight);
boxAnimationData.animationStep = 'falling';
boxAnimationData.bounceHeight = docHeight / 2 - img_box.height;
setInterval(animateBox, 30);
};
More interesting code is here :
function animateBox() {
if (boxAnimationData.animationStep == 'falling') dropBox();
else if (boxAnimationData.animationStep == 'bouncing') bounceBox();
}
function dropBox() {
ctx_overlay.clearRect(0, 0, docWidth, docHeight);
boxAnimationData.y += 3;
if (boxAnimationData.y + img_box.height > docHeight) {
boxAnimationData.animationStep = 'bouncing';
}
ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}
function bounceBox() {
ctx_overlay.clearRect(0, 0, docWidth, docHeight);
boxAnimationData.y += boxAnimationData.direction * 3;
if (boxAnimationData.y + img_box.height > docHeight) {
// reached floor ? swap direction
boxAnimationData.direction *= -1;
// and reduce jump height
boxAnimationData.bounceHeight *= 3 / 2;
boxAnimationData.bounceCount--;
if (!boxAnimationData.bounceCount) boxAnimationData.animationStep = '';
} else if (boxAnimationData.y < boxAnimationData.bounceHeight) {
boxAnimationData.direction *= -1;
}
ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}
I have a project I am trying to get an animated <canvas> working with Paper JS. What I am curious about is if there is anything built into PaperJS that allows the ability to detect interactivity between items (i.e. if a item is X distance from any other item on the layer). Here is what I have so far:
HTML
<canvas id="myCanvas" resize></canvas>
CSS
html, body{margin:0; padding: 0;}
#myCanvas{width: 100%; height: 100%;}
JS
$(function(){
var canvas = $('#myCanvas')[0];
paper.setup(canvas);
var viewSize = paper.view.size;
var itemCount = 20;
var theBall = new paper.Path.Rectangle({
point : [0,0],
size : 10,
fillColor : '#00a950',
});
var theBallSymbol = new paper.Symbol(theBall);
// Create and place symbol on view
for (var i = 1; i <= itemCount; i++) {
var center = paper.Point.random().multiply(viewSize);
var placedSymbol = theBallSymbol.place(center);
placedSymbol.scale(i / itemCount);
placedSymbol.data = {
origin : center,
direction : (Math.round(Math.random())) ? 'right' : 'left',
}
placedSymbol.onFrame = function(e){
var pathWidth = this.bounds.width * 20;
var center = this.data.origin;
var moveValue = this.bounds.width / 20;
if(this.data.direction == 'right'){
if(this.position.x < center.x + pathWidth){
this.position.x += moveValue;
} else{
this.position.x -= moveValue;
this.data.direction = 'left';
}
} else {
if(this.position.x > center.x - pathWidth){
this.position.x -= moveValue;
} else {
this.position.x += moveValue;
this.data.direction = 'right';
}
}
}
}
paper.view.onFrame = function (e){
// For entire view
for (var i = 0; i < itemCount; i++) {
var item = paper.project.activeLayer.children[i];
// I imagine I would need to do something here
// I tried a hitTest already, but I'm not sure
// that will give me the information I would need
}
}
});
JSFiddle
That part so far is working well. What I am curious about how I can do the following:
Whenever any given item (the squares) come within a distance of X between each other, create a line (path) between them
The idea is very similar to this page: http://panasonic.jp/shaver/lamdash/dna/
Any ideas would be greatly appreciated. Thanks!
Paper.js does not keep track of the inter-point distance between an item's center and all other items. The only way to gather that information is to manually loop through them.
In your case, I think it would be easiest to:
Create an array of lines
Only keep lines that might become shorter than the threshold value
Loop through the lines array on each onFrame() and adjust the opacity.
By only choosing lines that will come within a threshold value, you can avoid creating unnecessary paths that would slow the framerate. Without this, you'd be checking ~5 times as many items.
Here's a quick example:
$(function(){
var canvas = $('#myCanvas')[0];
paper.setup(canvas);
var viewSize = paper.view.size;
var itemCount = 60;
//setup arrays to change line segments
var ballArray = [];
var lineArray = [];
//threshold distance for lines
var threshold = Math.sqrt(paper.view.size.width*paper.view.size.height)/5;
var theBall = new paper.Path.Rectangle({
point : [0,0],
size : 10,
fillColor : '#00a950',
});
var theBallSymbol = new paper.Symbol(theBall);
// Create and place symbol on view
for (var i = 1; i <= itemCount; i++) {
var center = paper.Point.random().multiply(viewSize);
var placedSymbol = theBallSymbol.place(center);
placedSymbol.scale(i / itemCount);
placedSymbol.data = {
origin : center,
direction : (Math.round(Math.random())) ? 'right' : 'left',
}
// Keep each placedSymbol in an array
ballArray.push( placedSymbol );
placedSymbol.onFrame = function(e){
var pathWidth = this.bounds.width * 20;
var center = this.data.origin;
var moveValue = this.bounds.width / 20;
if(this.data.direction == 'right'){
if(this.position.x < center.x + pathWidth){
this.position.x += moveValue;
} else{
this.position.x -= moveValue;
this.data.direction = 'left';
}
} else {
if(this.position.x > center.x - pathWidth){
this.position.x -= moveValue;
} else {
this.position.x += moveValue;
this.data.direction = 'right';
}
}
}
}
// Run through every possible line
// Only keep lines whose length might become less than threshold
for (var i = 0; i < itemCount; i++) {
for (j = i + 1, point1 = ballArray[i].data.origin; j < itemCount; j++) {
if ( Math.abs(point1.y - ballArray[j].bounds.center.y) < threshold && Math.abs(point1.x - ballArray[j].data.origin.x) < 4 * threshold) {
var line = new paper.Path.Line( point1, ballArray[j].bounds.center ) ;
line.strokeColor = 'black';
line.strokeWidth = .5;
//note the index of the line's segments
line.point1 = i;
line.point2 = j;
if (line.length > 1.4 * threshold && ballArray[j].data.direction == ballArray[i].data.direction) {
line.remove();
}
else {
lineArray.push(line);
}
}
}
}
paper.view.onFrame = function (e){
// Update the segments of each line
// Change each line's opacity with respect to distance
for (var i = 0, l = lineArray.length; i < l; i++) {
var line = lineArray[i];
line.segments[0].point = ballArray[line.point1].bounds.center;
line.segments[1].point = ballArray[line.point2].bounds.center;
if(line.length < threshold) {
line.opacity = (threshold - line.length) / threshold;
}
else line.opacity = 0;
}
}
});