2013-08-24 38 views
0

我有這個可以繪製的畫布,但是由於我要在某個時間點上使用物理庫,所以我希望繪製稍微不詳細。 我正在考慮按照一定的時間間隔閱讀鼠標位置,然後只是畫一條直線到新的鼠標位置的東西。我用setInterval和setTimeout嘗試了一下,但它從來沒有做過任何接近我想看到的事情。有沒有人有任何建議,我可以做到這一點?在javascript中不太詳細的繪製

謝謝!

+0

嘗試其他方式:接受所有輸入,之後把它簡化。尋找「矢量平滑」技術。 – usr2564301

回答

1

這是一個Douglas-Peucker路徑簡化的JavaScript實現。

http://mourner.github.io/simplify-js/

(下文simplify.js查看完整的代碼。)

你也可以考慮使用,而不是線曲線減少點(路徑平滑)

平滑路徑是一個經常被考慮的任務:

Douglas Alan Schepers(來自w3c):

http://schepers.cc/getting-to-the-point

螺庫(如在Inkscape中所使用的,等等):

http://www.levien.com/spiro/

肯·菲斯登伯格Nilsen的(在SO頻繁貢獻者):

http://www.codeproject.com/Tips/562175/Draw-Smooth-Lines-on-HTML5-Canvas

Paper.js有平滑和簡化路徑的方法:

http://paperjs.org/tutorials/paths/smoothing-simplifying-flattening/

代碼Simplify.js(在http://mourner.github.io/simplify-js/ BSD許可證):

(function (global, undefined) { 
    // to suit your point format, run search/replace for '.x' and '.y'; 
    // to switch to 3D, uncomment the lines in the next 2 functions 
    // (configurability would draw significant performance overhead) 

    function getSquareDistance(p1, p2) { // square distance between 2 points 

    var dx = p1.x - p2.x, 
    //  dz = p1.z - p2.z, 
     dy = p1.y - p2.y; 


    return dx * dx + 
    //   dz * dz + 
      dy * dy; 
    } 


    function getSquareSegmentDistance(p, p1, p2) { // square distance from a point to a segment 

    var x = p1.x, 
     y = p1.y, 
    //  z = p1.z, 


     dx = p2.x - x, 
     dy = p2.y - y, 
    //  dz = p2.z - z, 


     t; 


    if (dx !== 0 || dy !== 0) { 

     t = ((p.x - x) * dx + 
    //    (p.z - z) * dz + 
      (p.y - y) * dy)/
       (dx * dx + 
    //     dz * dz + 
       dy * dy); 

     if (t > 1) { 
     x = p2.x; 
     y = p2.y; 
    //   z = p2.z; 

     } else if (t > 0) { 
     x += dx * t; 
     y += dy * t; 
    //   z += dz * t; 
     } 
    } 

    dx = p.x - x; 
    dy = p.y - y; 
    // dz = p.z - z; 

    return dx * dx + 
    //   dz * dz + 
      dy * dy; 
    } 

    // the rest of the code doesn't care for the point format 

    // basic distance-based simplification 

    function simplifyRadialDistance(points, sqTolerance) { 

    var i, 
     len = points.length, 
     point, 
     prevPoint = points[0], 
     newPoints = [prevPoint]; 

    for (i = 1; i < len; i++) { 
     point = points[i]; 

     if (getSquareDistance(point, prevPoint) > sqTolerance) { 
     newPoints.push(point); 
     prevPoint = point; 
     } 
    } 

    if (prevPoint !== point) { 
     newPoints.push(point); 
    } 

    return newPoints; 
    } 

    // simplification using optimized Douglas-Peucker algorithm with recursion elimination 

    function simplifyDouglasPeucker(points, sqTolerance) { 

    var len = points.length, 

     MarkerArray = (typeof Uint8Array !== undefined + '') 
        ? Uint8Array 
        : Array, 

     markers = new MarkerArray(len), 

     first = 0, 
     last = len - 1, 

     i, 
     maxSqDist, 
     sqDist, 
     index, 

     firstStack = [], 
     lastStack = [], 

     newPoints = []; 

    markers[first] = markers[last] = 1; 

    while (last) { 

     maxSqDist = 0; 

     for (i = first + 1; i < last; i++) { 
     sqDist = getSquareSegmentDistance(points[i], points[first], points[last]); 

     if (sqDist > maxSqDist) { 
      index = i; 
      maxSqDist = sqDist; 
     } 
     } 

     if (maxSqDist > sqTolerance) { 
     markers[index] = 1; 

     firstStack.push(first); 
     lastStack.push(index); 

     firstStack.push(index); 
     lastStack.push(last); 
     } 

     first = firstStack.pop(); 
     last = lastStack.pop(); 
    } 

    for (i = 0; i < len; i++) { 
     if (markers[i]) { 
     newPoints.push(points[i]); 
     } 
    } 

    return newPoints; 
    } 

    // both algorithms combined for awesome performance 

    function simplify(points, tolerance, highestQuality) { 

    var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1; 

    points = highestQuality ? points : simplifyRadialDistance(points, sqTolerance); 
    points = simplifyDouglasPeucker(points, sqTolerance); 

    return points; 
    }; 

    // export either as a Node.js module, AMD module or a global browser variable 

    if (typeof exports === 'object') { 
    module.exports = simplify; 

    } else if (typeof define === 'function' && define.amd) { 
    define(function() { 
     return simplify; 
    }); 

    } else { 
    global.simplify = simplify; 
    } 

}(this));