One handed draggable clock with Raphael - cannot get mouse click position

断了今生、忘了曾经 提交于 2019-12-11 06:07:32

问题


i followed this tutorial to build a one handed clock

<!-- language: lang-js -->
    window.onload = function(){

var canvas = Raphael("pane",0,0,500,500);

canvas.circle(200,150,100).attr("stroke-width",2);
canvas.circle(200,150,3).attr("fill","#000");

var angleplus = 360,rad = Math.PI / 180,
    cx = 200,cy =150 ,r = 85,
    startangle = -90,angle=15,x,y, endangle;

     for(i=1;i<=24;i++)
     {

         endangle = startangle + angle ;

         x = cx + r  * Math.cos(endangle * rad);
         y = cy + r * Math.sin(endangle * rad);
         canvas.text(x,y,""+(i%24));

          startangle = endangle;
     }

move = function(dx,dy){
    if(dx >=0 && dy <= 85)
        this.rotate(dx*0.25,200,150);
},
start = function(){

},
up = function(){};
var hand = canvas.path("M200 70L200 150").attr("stroke-width",3);



hand.drag(move,start,up);

};

Now i want the clock hand to be draggable (touchable via smartphones) to set a certain time. I don't want the clock to run, I just need it as an input device. I know how to calculate the angle but unfortunately I am not able to get the clicked mouse position only relative values to I don't know what. Does anybody have an idea?

EDIT: Now it should hopefully work. I also got it to run ... more or less. It is still a bit jumpy and there are a few points I still want to improve:

  • Prevent the circle from getting dragged
  • Having influence on the clock by the spinner
  • Using / Trying the actual start,end,move functions (I still couldn't succeed)
  • ...

回答1:


This will allow you to drag any of the hands, if this is the sort of thing you are after. There may be an easier way, but can't think of it for the moment.

We need to get the transform from the screen to the element (so that they are in the same coordinate space), getScreenCTM() will give us this, and we'll need to find the inverse to apply. (there may be a simpler way if everything is static and no transforms, but often elements are changed by various transforms and catches us out later).

We can get that transform matrix from

this.node.getScreenCTM().inverse()

We'll need to get the x,y from the Raph event and put it as an svg point so we can transfom, eg..

var pt = this.node.ownerSVGElement.createSVGPoint();
pt.x = x; pt.y = y;
var newpt = pt.matrixTransform( this.node.getScreenCTM().inverse() );

So the whole lot would look like...

hour_hand.drag( move, start, end );
minute_hand.drag( move, start, end );
hand.drag( move, start, end );

function move (dx,dy,x,y) {
    var pt = this.node.ownerSVGElement.createSVGPoint();
    pt.x = x; pt.y = y;
    var newpt = pt.matrixTransform( this.node.getScreenCTM().inverse()     );
    var angle = ( 90 + Math.atan2(pt.y - clock.attr('cy') - 5, pt.x - clock.attr('cx') - 5 ) * 180 / Math.PI + 360) % 360;
    this.rotate(angle, 200,150);
    this.angle = angle;
}

function start() {}

function end() {
     alert( parseInt( this.angle / 30  ) )
}

jsfiddle - drag arms to move

Edit: If you just want a click to move the 2nd hand for example, here is a slight modification, same principle, apart from I've put a background white rect in there to put the click handler on.

jsfiddle - click to move 2nd hand

Edit: There's an improved fiddle here which takes into account various postions of the clock with respect to other html on the screen etc. Where I've added the following...

var cpt = clock.node.ownerSVGElement.createSVGPoint();
cpt.x = clock.attr('cx');
cpt.y = clock.attr('cy');
cpt = cpt.matrixTransform(clock.node.getScreenCTM());

to take into account any position on the screen of the clock, and removed a bit of other redundant code.



来源:https://stackoverflow.com/questions/30500849/one-handed-draggable-clock-with-raphael-cannot-get-mouse-click-position

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