2

我有一个项目,我正在尝试<canvas>使用Paper JS制作动画。我很好奇的是,PaperJS 中是否有任何内置功能可以检测项目之间的交互性(即,如果一个项目与图层上的任何其他项目有 X 距离)。这是我到目前为止所拥有的:

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

到目前为止,该部分运行良好。我对如何执行以下操作感到好奇:

每当任何给定项目(正方形)彼此之间的距离为 X 时,在它们之间创建一条线(路径)

这个想法与这个页面非常相似:http: //panasonic.jp/shaver/lamdash/dna/

任何想法将不胜感激。谢谢!

4

1 回答 1

4

Paper.js 不跟踪项目中心与所有其他项目之间的点间距离。收集该信息的唯一方法是手动循环它们。

就您而言,我认为最简单的方法是:

  1. 创建一个行数组
  2. 只保留可能比阈值短的行
  3. 循环遍历每个 onFrame() 上的 lines 数组并调整不透明度。

通过仅选择将在阈值范围内的行,您可以避免创建会降低帧速率的不必要路径。如果没有这个,您将检查大约 5 倍的项目。

这是一个简单的例子:

$(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;
                }
            }


});
于 2013-08-16T22:19:31.840 回答