猿问

svg 上的矩阵变换:意外行为

我有一个 div,其中包含一个 300x300 像素的 SVG 图像和一个 1000x1000 的视图框。该图像描述了一个位于红色矩形之上的蓝色矩形。当我移动鼠标时,一个圆圈跟随图像内的鼠标位置:

一切都很完美,除了当我应用变换改变透视和旋转时,鼠标指针和圆心不再匹配:

http://img2.mukewang.com/61a88a280001b0cf04790335.jpg

代码在这里:


$(function() {

  $('#image').mousemove(function(event) {

    var svg = document.querySelector('svg');

    var pt = svg.createSVGPoint();

    pt.x = event.clientX;

    pt.y = event.clientY;

    pt = pt.matrixTransform(svg.getScreenCTM().inverse());

    overlay = document.getElementById('overlay');

    $('#overlay').html(

      "<circle cx='" + pt.x + "' cy='" + pt.y + "' r='50' stroke='#8f00ff' fill='transparent' stroke-width='10' /></svg>"

    );

    refresh = $("#overlay").html();

    $("#overlay").html( refresh )

  });

});

function Transform() {

  $('#image').css({

    transformOrigin: '500px 500px',

    transform: 'perspective(100px) rotateX(5deg)'

  });

}

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id='image' tabindex='0' >

  <svg id='svgmap' width='300' height='300' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1000 1000'>

    <rect x='0' y='0' width='1000' height='1000' fill='red' />

    <rect x='250' y='250' width='500' height='500' stroke='yellow' fill='blue' stroke-width='10' />

    <g id='overlay'></g>

  </svg>

</div>

<button onclick='Transform()'>Transform</button>

我的目标是保持紫色圆圈中心和鼠标指针之间的匹配,即使对对象应用了变换。有没有办法做到这一点?


潇湘沐
浏览 260回答 2
2回答

牛魔王的故事

在您的代码中#image是一个 div。为了使其工作,您需要将转换应用于 svg 元素 (#svgmap),并且转换必须是 svg 转换。$(function() {&nbsp; $('#svgmap').mousemove(function(event) {&nbsp; &nbsp; var svg = document.querySelector('svg');&nbsp; &nbsp; var pt = svg.createSVGPoint();&nbsp; &nbsp; pt.x = event.clientX;&nbsp; &nbsp; pt.y = event.clientY;&nbsp; &nbsp; pt = pt.matrixTransform(svg.getScreenCTM().inverse());&nbsp; &nbsp; overlay = document.getElementById('overlay');&nbsp; &nbsp; $('#overlay').html(&nbsp; &nbsp; &nbsp; "<circle cx='" + pt.x + "' cy='" + pt.y + "' r='50' stroke='#8f00ff' fill='transparent' stroke-width='10' /></svg>"&nbsp; &nbsp; );&nbsp; &nbsp; refresh = $("#layer_wafer").html();&nbsp; &nbsp; $("#layer_wafer").html( refresh )&nbsp; });});function Transform() {&nbsp; svgmap.setAttributeNS(null,"transform", "skewX(-20) translate(100)");}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><div id='image' tabindex='0' >&nbsp; <svg id='svgmap' width='300' height='300' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1000 1000' transform="">&nbsp; &nbsp; <rect x='0' y='0' width='1000' height='1000' fill='red' />&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; <rect x='250' y='250' width='500' height='500' stroke='yellow' fill='blue' stroke-width='10' />&nbsp; &nbsp; <g id='overlay'></g>&nbsp; </svg></div><button onclick='Transform()'>Transform</button>我知道您需要 3D css 转换,但这(至少现在)不起作用。这是一篇文章,您可以在其中阅读有关 svg 中 3d 变换的更多信息:https&nbsp;:&nbsp;//oreillymedia.github.io/Using_SVG/extras/ch11-3d.html在文章中您可以阅读:本节中描述的所有 3D 变换函数应该被视为“未来”

凤凰求蛊

我已经以最丑陋的方式解决了这个问题。只需将鼠标光标隐藏在 div 上即可。丑陋的。但有效。$(function() {&nbsp; $('#image').mousemove(function(event) {&nbsp; &nbsp; var svg = document.querySelector('svg');&nbsp; &nbsp; var pt = svg.createSVGPoint();&nbsp; &nbsp; pt.x = event.clientX;&nbsp; &nbsp; pt.y = event.clientY;&nbsp; &nbsp; pt = pt.matrixTransform(svg.getScreenCTM().inverse());&nbsp; &nbsp; overlay = document.getElementById('overlay');&nbsp; &nbsp; $('#overlay').html(&nbsp; &nbsp; &nbsp; "<circle cx='" + pt.x + "' cy='" + pt.y + "' r='50' stroke='#8f00ff' fill='transparent' stroke-width='10' /></svg>"&nbsp; &nbsp; );&nbsp; &nbsp; refresh = $("#overlay").html();&nbsp; &nbsp; $("#overlay").html( refresh )&nbsp; });});function Transform() {&nbsp; $('#image').css({&nbsp; &nbsp; transformOrigin: '500px 500px',&nbsp; &nbsp; transform: 'perspective(100px) rotateX(5deg)'&nbsp; });}div#image {&nbsp; cursor: none;}<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><div id='image' tabindex='0' >&nbsp; <svg id='svgmap' width='300' height='300' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1000 1000'>&nbsp; &nbsp; <rect x='0' y='0' width='1000' height='1000' fill='red' />&nbsp; &nbsp; <rect x='250' y='250' width='500' height='500' stroke='yellow' fill='blue' stroke-width='10' />&nbsp; &nbsp; <g id='overlay'></g>&nbsp; </svg></div><button onclick='Transform()'>Transform</button>我必须做一些优化以减少 DIV 上方和任何其他页面元素之间的鼠标光标位置差距,但这对我来说是可以接受的。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答