【问题标题】:mcanvas vs svg vs html5 canvasmcanvas vs svg vs html5画布
【发布时间】:2013-07-19 23:52:24
【问题描述】:

我最近在具有 Raphael 画布的移动浏览器中进行了测试,我们可以在其中使用平板电脑绘制线条等。

例如,使用 svg 在浏览器上绘图时速度和精度不足,即使在移动过程中没有停止触摸等,绘图时线条也会中断。

所以我正在研究绘图应用程序中使用的东西,它们非常适合触摸屏。

如果我们想在移动浏览器上有一个绘图应用程序,它是最好的 canvas 或 svg 或者两者都不是,因为我们不想在绘图时断线?

我可以在哪里开始研究更多关于 android 用于绘图的绘图 api,这些绘图被“笔备忘录、S2 和其他触摸应用程序”使用。

更新:查看jsfiddle

var canvas = $("#canvas");
paper = Raphael("canvas");
var clicking = false;
var line;
var pathArray = [];

 canvas.bind("mousedown", _mousedownHandler);
 canvas.bind("touchstart", _mousedownHandler);
function _mousedownHandler(event){
     clicking = true;
 // _drawArrowLineBegin(e);
        if(event.type == "touchstart"){
            event.preventDefault(); 
            event = event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];
        }
    _drawFreeLineBegin(event);
};

function _mousemoveHandler(event){
 // _drawArrowLineMove(event);
        if(event.type == "touchmove"){
            event.preventDefault(); 
            event = event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];
        }
    _drawFreeLineMove(event);
};
function _mouseupHandler(event){
    clicking = false;
};
function _enableEvents(){
           canvas.bind("mousemove.mmu", _mousemoveHandler);
        canvas.one("mouseup.mmu", _mouseupHandler);
        canvas.bind("touchmove.mmu", _mousemoveHandler);
        canvas.one("touchend.mmu", _mouseupHandler);
};
function _drawArrowLineBegin(e) {
    clicking = true;
        line = paper.path("M" + (e.offsetX || e.clientX) + " " + (e.offsetY || e.clientY) + "L" + (e.offsetX || e.clientX) + " " + (e.offsetY || e.clientY)).attr({stroke:'#FF0000', 'stroke-width': 2, 'arrow-end': 'classic-wide-long'});
    pathArray = line.attr("path");
 _enableEvents();
    }
function _drawArrowLineMove(e){
        if(clicking == false) return;
    if (pathArray[1][1] != undefined) { // not IE 8
        pathArray[1][1] = e.offsetX || e.clientX;
        pathArray[1][2] = e.offsetY || e.clientY;
    } else {
        pathArray = pathArray.replace(/L\d+ \d+$/, "L" + e.offsetX + " " + e.offsetY);
    }

    line.attr({path: pathArray});
}
function _drawFreeLineBegin(e) {
    clicking = true;
       line =  paper.path("M"
                + (e.pageX) + ","
                + (e.pageY)).attr({stroke:'#FF0000', 'stroke-width': 2});
     pathArray = line.attr("path");
_enableEvents();
    }
function _drawFreeLineMove(e){
        if(clicking == false) return;
    line.attr("path",line.attr("path")
                        + "L"
                                    + (e.pageX)
                                    + ","
                                    + (event.pageY));
}

【问题讨论】:

  • 在我看来更像是一个实现问题。两者都适合您提到的内容。你有什么方法可以为你的应用程序部分创建一个小提琴?
  • @ShamasisBhattacharya 刚刚用 jsfiddle 更新
  • 实现需要做一些改进。我会花一些时间来制作一个小提琴。

标签: android canvas svg raphael


【解决方案1】:

提到的关于速度和性能的问题是 SVG 中使用的 JavaScript 库的固有问题。在您的小提琴中,绘图中的性能问题主要是因为路径数组的不断扩展以及整个路径数组在每次触摸移动时都会重新处理的事实。没有比解决它更简单的方法来解决这个问题。

我已经用纯 Raphael(没有 jQuery)重新创建了你的实现。 http://jsfiddle.net/shamasis/kUQ7E/

实现有两个方面:

  1. 绕过了Raphael的重磅attr函数,直接使用doodle.node.setAttribute('d', pathstring);设置元素的路径
  2. 它使用超时来忽略可容忍间隔内的上下触摸。

小提琴(截至修订版 24)看起来像:

Raphael("canvas", function () {
    var win = Raphael._g.win,
        doc = win.document,
        hasTouch = "createTouch" in doc,

        M = "M",
        L = "L",
        d = "d",
        COMMA = ",",
        // constant for waiting doodle stop
        INTERRUPT_TIMEOUT_MS = hasTouch ? 100 : 1,
        // offset for better visual accuracy
        CURSOR_OFFSET = hasTouch ? 0 : -10,

        paper = this,
        path = "", // hold doodle path commands
        // this element draws the doodle
        doodle = paper.path(path).attr({
            "stroke": "rgb(255,0,0)"
        }),

        // this is to capture mouse movements
        tracker = paper.rect(0, 0, paper.width, paper.height).attr({
            "fill": "rgb(255,255,255)",
            "fill-opacity": "0.01"
        }),
        active = false, // flag to check active doodling
        repath = false, // flag to check if a new segment starts
        interrupt; // this is to connect jittery touch

    tracker.mousedown(function () {
        interrupt && (interrupt = clearTimeout(interrupt));
        active = true;
        repath = true;
    });

    tracker.mousemove(function (e, x, y) {
        // do nothing if doodling is inactive
        if (!active) {
            return;
        }

        // Fix for Raphael's touch xy bug
        if (hasTouch && 
                (e.originalEvent.targetTouches.length === 1)) {
            x = e.clientX + 
                (doc.documentElement.scrollTop || doc.body.scrollTop || 0);
            y = e.clientY + 
                (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0);
            e.preventDefault();
        }

        // Insert move command for a new segment
        if (repath) {
            path += M + (x + CURSOR_OFFSET) + COMMA + 
                    (y + CURSOR_OFFSET);
            repath = false;
        }
        path += L + (x + CURSOR_OFFSET) + COMMA + 
                (y + CURSOR_OFFSET); // append line point

        // directly access SVG element and set path
        doodle.node.setAttribute(d, path);
    });

    // track window mouse up to ensure mouse up even outside
    // paper works.
    Raphael.mouseup(function () {
        interrupt && (interrupt = clearTimeout(interrupt));
        // wait sometime before deactivating doodle
        interrupt = setTimeout(function () {
            active = false;
        }, INTERRUPT_TIMEOUT_MS);
    });
});

【讨论】:

  • 您的代码运行得更好。你能解释一下你评论的 Raphael touch 的修复方法吗?
  • 你能告诉我为什么你不使用 jquery 来处理鼠标/触摸事件吗?
  • (1) Raphael Touch 修复可防止在某些触摸设备(包括 iOS 6)上获取触摸 x,y 的 NaN,NaN。 (2) 只使用一个库 + Raphael 的事件处理程序更轻量(+ 更原生)!
  • 我正在尝试您的示例而不使用矩形的事件,使用 Rahphael mouseevents,它在使用鼠标而不是触摸板时工作正常。你能告诉我我做错了什么吗? jsfiddle.net/stackit/aUPwG/1
  • 为什么要这样做?整个 Windows 的鼠标按下都会被这个触发。
猜你喜欢
  • 2011-08-18
  • 2013-10-19
  • 2012-06-26
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2011-04-18
  • 2017-07-20
  • 2011-05-19
相关资源
最近更新 更多