如何在mousemove事件中使用requestAnimationFrame? [英] How to use requestAnimationFrame in mousemove event?

查看:116
本文介绍了如何在mousemove事件中使用requestAnimationFrame?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在基于SVG的Web应用程序中,用户可以选择大量形状(甚至800个或更多),可以在屏幕上四处移动它们,就像可以想象的那样,它会严重影响帧速率.阅读了requestAnimationFrame的优点后,从昨天开始我一直在尝试将其合并到我的mousemove函数中,希望通过结合使用节流& requestAnimationFrame,我可以达到平滑的帧率.

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.

这里是jsFiddle,我要在其中移动mousemove上的600 svg形状.现在忽略节流,如何将requestAnimationFrame合并到mousemove函数中.

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代码

<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 + ')');

        }

推荐答案

基本上,您需要将draggroup.setAttribute()调用移至另一个函数.由于只需要在鼠标按下时进行动画处理,因此添加另一个变量以指示是否在拖动,只有在这种情况下才调用requestAnimationFrame.

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...
}

您已经将组(dxdy)的更新位置存储在单独的变量中,因此从mousemove()中删除draggroup.setAttribute()调用并添加以上修改,您应该会很好!

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!

这篇关于如何在mousemove事件中使用requestAnimationFrame?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆