我正在使用Snap.svg和jQuery,并且正在创建此Bitmoji并试图使他的眼睛跟随鼠标光标。
除了眼睛,一切都很好。它们在移动光标时正在变形和旋转,但不能正确地100%移动,我不知道为什么。
这是我在JSFiddle中的代码:http://jsfiddle.net/bmp5j4x9/1/
调整结果框的大小,使其更大并在鼠标周围移动,我想您会明白我的意思的。或看看http://dante-c.be。
这是jQuery部分:
<%= radio_button_tag 'user[tenant_id]', '' ,:checked => (@current_tenant.id == t.id) %>
如Nikos所述,尝试通过以下代码替换OnMouseMove函数来限制/反跳:
var s = Snap(420, 420).attr({ viewBox: "0 0 120 120" });
$(s.node).appendTo(".button");
var image = s.paper.image('https://render.bitstrips.com/v2/cpanel/10220069-circle-357822728_5-s4-v1.png?palette=1', 0, 0, 1, 1);
image = image.pattern().attr({
patternContentUnits: "objectBoundingBox",
patternUnits: "",
width: "100%", height: "100%", viewBox: ""
});
var bitmojiCircle = s.circle(60, 60, 39).attr({ fill: image });
var circleX = 50, circleY = 63, circleRadius = 4.5;
var bigEyeCircle = s.circle(circleX, circleY, circleRadius);
var L1 = s.path("M "+circleX+" "+circleY +"L 0 0").attr({stroke: "blue"});
bigEyeCircle.attr({
fill: "#bada55",
stroke: "#000",
strokeWidth: 1
});
var smallEyeCircle = s.circle(0,0,3.5).attr({ fill: "red" });
var opacityCircle = s.circle(60, 60, 39).attr({ fill: "rgba(255,255,255,0.7)" });
var menuButton = s.path("M58.486 56.324H57.19c-.48 0-.866.387-.866.865v1.29c0 .48.387.86.865.86h1.29c.48 0 .86-.39.86-.87v-1.29c0-.48-.39-.87-.87-.87zm-4.324 0h-1.297c-.478 0-.865.387-.865.865v1.29c0 .48.387.86.865.86h1.297c.478 0 .865-.39.865-.87v-1.29c0-.48-.387-.87-.865-.87zM58.486 52H57.19c-.48 0-.866.387-.866.865v1.297c0 .478.387.865.865.865h1.29c.48 0 .86-.387.86-.865v-1.297c0-.478-.39-.865-.87-.865zm-4.324 0h-1.297c-.478 0-.865.387-.865.865v1.297c0 .478.387.865.865.865h1.297c.478 0 .865-.387.865-.865v-1.297c0-.478-.387-.865-.865-.865zm12.973 4.324h-1.297c-.478 0-.865.387-.865.865v1.29c0 .48.387.86.865.86h1.297c.478 0 .865-.39.865-.87v-1.29c0-.48-.387-.87-.865-.87zm-4.324 0h-1.29c-.48 0-.86.387-.86.865v1.29c0 .48.39.86.87.86h1.3c.48 0 .87-.39.87-.87v-1.29c0-.48-.38-.87-.86-.87zM67.14 52h-1.3c-.48 0-.866.387-.866.865v1.297c0 .478.387.865.865.865h1.29c.48 0 .86-.387.86-.865v-1.297c0-.478-.39-.865-.87-.865zm-4.324 0H61.52c-.48 0-.865.387-.865.865v1.297c0 .478.386.865.865.865h1.297c.48 0 .866-.387.866-.865v-1.297c0-.478-.386-.865-.864-.865zM58.49 64.973h-1.3c-.48 0-.866.387-.866.865v1.297c0 .478.387.865.865.865h1.29c.48 0 .86-.387.86-.865v-1.297c0-.478-.39-.865-.87-.865zm-4.325 0h-1.297c-.478 0-.865.387-.865.865v1.297c0 .478.387.865.865.865h1.297c.478 0 .865-.387.865-.865v-1.297c0-.478-.388-.865-.866-.865zm4.324-4.324h-1.3c-.48 0-.87.38-.87.86v1.29c0 .48.38.86.86.86h1.29c.48 0 .86-.39.86-.87V61.5c0-.48-.39-.864-.87-.864zm-4.33 0h-1.3c-.48 0-.87.38-.87.86v1.29c0 .48.38.86.86.86h1.29c.472 0 .86-.39.86-.87V61.5c0-.48-.39-.864-.867-.864zm12.97 4.32h-1.29c-.48 0-.87.38-.87.86v1.29c0 .48.38.86.86.86h1.29c.48 0 .86-.39.86-.87v-1.29c0-.48-.387-.87-.865-.87zm-4.33 0h-1.29c-.48 0-.87.38-.87.86v1.29c0 .48.38.86.86.86h1.3c.48 0 .862-.39.862-.87v-1.29c0-.48-.39-.87-.867-.87zm4.32-4.33h-1.3c-.48 0-.87.38-.87.86v1.3c0 .48.384.86.862.86h1.3c.476 0 .863-.39.863-.87V61.5c0-.48-.388-.864-.866-.864zm-4.33 0H61.5c-.48 0-.864.38-.864.86v1.3c0 .48.387.86.866.86H62.8c.48 0 .87-.39.87-.87V61.5c0-.48-.383-.864-.86-.864z").attr({
class: "menu-button",
fill: "#9B9B9B",
fillRule: "nonzero"
});
var c1 = s.circle(60, 60, 53).attr({ stroke: "#9B9B9B", transform: "rotate(90 60 60)" });
var c2 = s.circle(60, 7, 2).attr({ fill: "#9B9B9B" });
var c3 = s.circle(60, 113, 2).attr({ fill: "#9B9B9B" });
var c4 = s.circle(113, 60, 2).attr({ fill: "#9B9B9B" });
var c5 = s.circle(7, 60, 2).attr({ fill: "#9B9B9B" });
var outerCircles = s.group(c1, c2, c3, c4, c5).attr({ class: "outer-circle" });
var fullSVG = s.group(bitmojiCircle, bigEyeCircle, L1, smallEyeCircle, opacityCircle, menuButton, outerCircles).attr({ fill: "none", fillRule: "evenodd" });
function OnMouseMove(evt) {
L1.attr({ d: "M "+circleX+" "+circleY +"L "+evt.clientX+" "+evt.clientY });
var totalLength = L1.getTotalLength();
if (totalLength < circleRadius) {
smallEyeCircle.attr({ cx: evt.clientX , cy: evt.clientY });
} else {
var PAL = L1.getPointAtLength(circleRadius);
smallEyeCircle.attr({ cx: PAL.x , cy: PAL.y });
}
}
document.onmousemove = OnMouseMove;
这似乎不起作用。
我找到了一个更好的解决方案,但是它仍然不能100%起作用,眼球可以移动的区域太大,但是我不知道如何缩小它。 这是更新的小提琴:http://jsfiddle.net/bmp5j4x9/3/
答案 0 :(得分:0)
正如我所说,您正在检测鼠标相对于文档的位置,并且正在使用这些坐标在尺寸为120/120的SVG画布内绘制。这行不通。 接下来是一个示例(Javascript),其中该行正确地跟随鼠标
let m = {}
test.addEventListener("mousemove",(e)=>{
// draw the line on mousemove
m=oMousePosSVG(e);
_line.setAttributeNS(null,"x2",m.x);
_line.setAttributeNS(null,"y2",m.y);
})
function oMousePosSVG(e) {
// a function to detect the mouse position inside an SVG
var p = test.createSVGPoint();
p.x = e.clientX;
p.y = e.clientY;
var ctm = test.getScreenCTM().inverse();
var p = p.matrixTransform(ctm);
return p;
}
<svg id="test" viewBox="0 0 120 120" width="100vw" height="100vh">
<circle cx="60" cy="60" r="20" fill="#d9d9d9" />
<line id="_line" x1="55" y1="60" stroke="blue" />
</svg>
另一种解决方案是让事物随您使用,但是根据文档大小重新计算鼠标位置:
let w = window.innerWidth;
let h = window.innerHeight;
let m = {}
document.addEventListener("mousemove",(e)=>{
//get the mouse position
m=oMousePos(e);
//calculate the x2 and y2 for the line in function of the size of the window
let x2 = map(m.x, 0, w, 0, 120)
let y2 = map(m.y, 0, h, 0, 120)
// set the attributes x2 and y2 for the line
_line.setAttributeNS(null,"x2",x2);
_line.setAttributeNS(null,"y2",y2);
})
function init(){
// a function to get the size of the window on resize
w = window.innerWidth;
h = window.innerHeight;
}
// you call the init on resize
setTimeout(function() {
init();
addEventListener('resize', init, false);
}, 15);
// a function to get the mouse position
function oMousePos(evt) {
return {
x: evt.clientX,
y: evt.clientY
}
}
function map(n, a, b, _a, _b) {
let d = b - a;
let _d = _b - _a;
let u = _d / d;
return _a + n * u;
}
svg {
border: 1px solid;
position: absolute;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
<svg id="test" viewBox="0 0 120 120" width="240" >
<circle cx="60" cy="60" r="20" fill="#d9d9d9" />
<line id="_line" x1="55" y1="60" stroke="blue" />
</svg>
希望对您有帮助。
OP指出实际上他们希望红色小圆圈跟随鼠标。在这种情况下,您需要计算眼睛中心与鼠标之间的角度,并使用该角度绘制红色圆圈:
let m = {}
let c = {x:55,y:60}// the center of the eye
let r = whitecircle.getAttribute("r") - redcircle.getAttribute("r") - .5;
// where .5 is 1/2 stroke-width
test.addEventListener("mousemove",(e)=>{
// draw the line on mousemove
m=oMousePosSVG(e);
//_line.setAttributeNS(null,"x2",m.x);
//_line.setAttributeNS(null,"y2",m.y);
var angle = getAngle(m,c)
//this are the coordinates for the center of the red circle
var x2 = c.x + r * Math.cos(angle);
var y2 = c.y + r * Math.sin(angle);
redcircle.setAttributeNS(null,"cx",x2);
redcircle.setAttributeNS(null,"cy",y2);
})
function oMousePosSVG(e) {
// a function to detect the mouse position inside an SVG
var p = test.createSVGPoint();
p.x = e.clientX;
p.y = e.clientY;
var ctm = test.getScreenCTM().inverse();
var p = p.matrixTransform(ctm);
return p;
}
function getAngle(p1,p2){
// a function to calculate the angle between two points p1 and p2
var deltaX = p1.x - p2.x;
var deltaY = p1.y - p2.y;
return Math.atan2(deltaY, deltaX);
}
<svg id="test" viewBox="0 0 120 120" width="100vw" height="100vh">
<circle cx="60" cy="60" r="20" fill="#d9d9d9" />
<circle id="whitecircle" cx="55" cy="60" r="5" fill="#fff" stroke="black" />
<circle cx="55" cy="60" r="3" fill="#f00" id="redcircle" />
<!--<line id="_line" x1="55" y1="60" stroke="blue" />-->
</svg>