How to use requestAnimationFrame in mousemove event?

China☆狼群 提交于 2019-12-24 12:32:16

问题


In my SVG based web application, a user can select a large number of shapes (even 800 or more) & move them about on the screen, which as one can imagine severely impacts the framerate. After reading the merits of requestAnimationFrame, I have been working since yesterday trying to incorporate it into my mousemove function, with the hope that by using a combination of throttling & requestAnimationFrame, I can get to a smooth framerate.

Here is the jsFiddle in which I am moving 600 svg shapes on mousemove. Ignoring throttling for now, how can I incorporate requestAnimationFrame into the mousemove function.

http://jsfiddle.net/rehankhalid/5t5pX/

HTML CODE

<svg width="1200" height="800">
<symbol>
    <g id="symbol1">
    <path fill="#3ab6d1" d="M27.7,1.1C16-2,3.9,5.1,0.8,16.9s4,23.8,15.7,26.9c11.7,3.1,23.8-4,26.9-15.7C46.6,16.3,39.6,4.2,27.7,1.1z   M38.3,26.9C36,35.7,26.9,41,18,38.7C9.1,36.4,3.8,27.3,6.1,18.5C8.4,9.6,17.5,4.3,26.4,6.6C35.3,9,40.6,18,38.3,26.9z"/>
    <g fill="#d5e1db">
    <path d="m25.8,.8c2.5,.4 4.8,1.2 7,2.5l-2.9,4.6c-1.5-.8-3.1-1.4-4.8-1.7l.7-5.4z"/>
    <path d="m13.9,2.2l1.7,5.1c-1.5,.7-3,1.5-4.3,2.7l-3.8-3.9c.9-.8 1.9-1.5 2.9-2.2 1.2-.7 2.3-1.3 3.5-1.7z"/>
    </g>
    <path fill="#196275" d="m26.4,38.5l1.8,5.2c-2.5,.7-4.9,.9-7.4,.8l.6-5.4c1.6,0 3.3-.2 5-.6z"/>
    <path fill="#42aec2" d="M6.1,18.4C8.4,9.5,17.5,4.2,26.4,6.5S40.7,18,38.4,26.8C36,35.7,26.9,41,18,38.7C9.1,36.3,3.7,27.2,6.1,18.4  z"/>
    <path fill="#d2dfdd" d="m28.7,25.9l.5-4.9 9.5-1.3c0,.3 .1,.6 .2,.8 .4,2.9 0,5.8-1,8.3l-9.2-2.9z"/>
    <path fill="#1b6273" d="m19.7,29.3h4.9l2.1,9.4c-.3,.1-.6,.2-.8,.2-2.9,.6-5.7,.5-8.4-.3l2.2-9.3z"/>
    <path fill="#368098" d="m15.9,25.8l3.6,3.4-4.8,8.3c-.3-.1-.5-.3-.8-.4-2.6-1.5-4.6-3.5-6-5.9l8-5.4z"/>
    <path fill="#d2dfdd" d="m18.6,16.5l-3,3.9-8.7-4c.1-.3 .2-.5 .3-.8 1.2-2.7 3.1-4.9 5.3-6.5l6.1,7.4z"/>
    <path fill="#bde2e9" d="m26.4,32.1l-8.4-.5-4.9-6.8 2.3-8 7.7-3.2 7.3,4 1.5,8.2-5.5,6.3z"/>
    </g>
</symbol>
<g id="default">
<g id="my-element">

</g>
</g>


<g id="draggroup">

</g>

</svg>

Javascript

document.addEventListener('mousedown', mousedown, false);


        var element = document.getElementById('my-element');
        var defaultg = document.getElementById('default');
        var mainsvg = document.getElementsByTagName('svg')[0];
        var draggroup = document.getElementById('draggroup');
        var svgns = "http://www.w3.org/2000/svg";



        var x = 0, y = 0;
        var scale = '0.25';
        for (var i = 0; i < 600; i++) {
            var useelement = document.createElementNS(svgns, "use");
            useelement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#symbol1');
            useelement.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(' + scale + ')');

            x += 12;
            if (x === 240) {
                x = 0;
                y += 12;
            }

            element.appendChild(useelement);

        }


        var bbox = element.getBBox();
        var selectionRect = document.createElementNS(svgns, "rect");
        selectionRect.setAttribute('id', 'selectionrect');
        selectionRect.setAttribute('x', bbox.x);
        selectionRect.setAttribute('y', bbox.y);
        selectionRect.setAttribute('width', bbox.width);
        selectionRect.setAttribute('height', bbox.height);
        selectionRect.setAttribute('fill', 'grey');
        selectionRect.setAttribute('opacity', '0.2');

        draggroup.appendChild(selectionRect);


        var dx = 0, dy = 0, mx = 0, my = 0;
        var rectdx = 0, rectdy = 0;
        var elementdx = 0, elementdy = 0;

        function getSvgCordinates(event) {
            var m = mainsvg.getScreenCTM();
            var p = mainsvg.createSVGPoint();
            var x, y;

            x = event.pageX;
            y = event.pageY;

            p.x = x;
            p.y = y;
            p = p.matrixTransform(m.inverse());

            x = p.x;
            y = p.y;

            x = parseFloat(x.toFixed(3));
            y = parseFloat(y.toFixed(3));

            return {x: x, y: y};
        }

        function mousedown(event) {

            if (event.target.id === 'selectionrect') {
                var svgXY = getSvgCordinates(event);
                mx = svgXY.x; // mouse down x
                my = svgXY.y;// mouse down y


                draggroup.appendChild(element);

                document.addEventListener('mousemove', mousemove, false);
                document.addEventListener('mouseup', mouseup, false);
            }
        }

        function mouseup() {
            document.removeEventListener('mousemove', mousemove, false);
            document.removeEventListener('mouseup', mouseup, false);

            draggroup.setAttribute('transform', 'translate(0,0)');

            rectdx += dx;
            rectdy += dy;
            elementdx += dx;
            elementdy += dy;

            selectionRect.setAttribute('transform', 'translate(' + rectdx + ',' + rectdy + ')');
            element.setAttribute('transform', 'translate(' + elementdx + ',' + elementdy + ')');

            defaultg.appendChild(element);

            dx = 0;
            dy = 0;
        }

        function mousemove(event) {
            var svgXY = getSvgCordinates(event);
            dx = svgXY.x - mx;
            dy = svgXY.y - my;

            draggroup.setAttribute('transform', 'translate(' + dx + ',' + dy + ')');

        }

回答1:


Basically, you'd need to move the draggroup.setAttribute() calls to another function. Since you only need to animate when the mouse is down, add another variable to indicate whether you're dragging or not, and only call requestAnimationFrame when that's the case.

var isDragging = false;
function update() { // New function
  if (isDragging) {
    requestAnimationFrame(update); // Call self again, if still dragging
  }
  draggroup.setAttribute('transform', 'translate(' + dx + ',' + dy + ')');
}
function mousedown(event) {
  if (event.target.id === 'selectionrect') {
    isDragging = true;
    requestAnimationFrame(update); // Start animation loop
    // existing logic here...
  }
}
function mouseup() {
  isDragging = false;
  // existing logic here...
}

You're already storing the updated location for the group (dx, dy) in a separate variable, so remove the draggroup.setAttribute() call from mousemove() and add the above modifications, and you should be good!



来源:https://stackoverflow.com/questions/21249493/how-to-use-requestanimationframe-in-mousemove-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!