在SVG元素中保留变换
Preserve a Transform in an SVG element
我有一个SVG形状(它很复杂,为了理解起见,我把它简化了),我需要对它进行转换。我的要求是
- 鼠标悬停时,该组应缩放为2倍
- 当鼠标移出时,组应缩回到1x
- 拖动时,应预先保存组比例
到目前为止,除了一个问题,我已经完成了所有的部分。当我试图将鼠标悬停在组上时,拖动该元素后,它会恢复到其原始位置。我不明白为什么会发生这种事。这是一把正在工作的小提琴。有人能帮我吗?
index.html
<svg width="400" height="400" style="background-color: red">
<g id="op" class="operator" transform="translate(0,0)">
<circle class="head" cx="50" cy="50" r="20" style="fill: yellow"></circle>
<circle cx="40" cy="40" r="10" style="fill: blue"></circle>
<circle cx="60" cy="40" r="10" style="fill: blue"></circle>
</g>
</svg>
script.js
d3.selectAll('.operator')
.on('mouseenter', function () {
console.log('Mouse Enter');
var c = d3.select(this).select('.head');
var x = c.attr('cx');
var y = c.attr('cy');
var scale = 2;
var scaleX = -1 * x * (scale - 1);
var scaleY = -1 * y * (scale - 1);
d3.select(this).attr('transform', 'translate(' + scaleX + ',' + scaleY + ')' + 'scale(' + scale + ')');
})
.on('mouseleave', function () {
console.log('Mouse Leave');
var c = d3.select(this).select('.head');
var x = c.attr('cx');
var y = c.attr('cy');
var scale = 1;
var scaleX = -1 * x * (scale - 1);
var scaleY = -1 * y * (scale - 1);
d3.select(this).attr('transform', 'translate(' + scaleX + ',' + scaleY + ')' + 'scale(' + scale + ')');
})
.call(d3.behavior.drag()
.origin(function () {
var t = d3.select(this);
return {
x: d3.transform(t.attr("transform")).translate[0],
y: d3.transform(t.attr("transform")).translate[1]
};
})
.on('drag', function () {
var oldScale = d3.transform(d3.select(this).attr('transform')).scale;
d3.select(this).attr('transform', 'translate(' + d3.event.x + ',' + d3.event.y + ')scale(' + oldScale + ')');
}))
正如@PhilAnderson所说,你不应该混合translate
和cx/cy
。事实上,按照嵌套元素的方式,您应该只是在转换。在SVG中翻译g
,然后在g
中翻译圆圈。纠正这一点,事情变得简单多了:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<svg width="400" height="400" style="background-color: red">
<g id="op" class="operator" transform="translate(50,50)">
<circle class="head" r="20" style="fill: yellow"></circle>
<circle transform="translate(-10,0)" r="10" style="fill: blue"></circle>
<circle transform="translate(10,0)" r="10" style="fill: blue"></circle>
</g>
</svg>
<script>
d3.select('.operator')
.on('mouseenter', function() {
console.log('Mouse Enter');
var self = d3.select(this),
xy = d3.transform(self.attr('transform')).translate,
scale = 2;
self.attr('transform', 'translate(' + xy[0] + ',' + xy[1] + ')' + 'scale(' + scale + ')');
})
.on('mouseleave', function() {
console.log('Mouse Leave');
var self = d3.select(this),
xy = d3.transform(self.attr('transform')).translate,
scale = 1;
self.attr('transform', 'translate(' + xy[0] + ',' + xy[1] + ')' + 'scale(' + scale + ')');
})
.call(d3.behavior.drag()
.on('drag', function() {
var self = d3.select(this),
oldScale = d3.transform(self.attr('transform')).scale;
self.attr('transform', 'translate(' + d3.event.x + ',' + d3.event.y + ')scale(' + oldScale + ')');
}))
</script>
</body>
</html>
看起来您将cx和cy属性与translate混淆了。
在mouseenter和mouseleave中,您可以根据cx和cy的值移动形状,但在拖动事件中,您只需使用事件的x和y值进行平移。
解决这个问题的一种方法是在拖动事件中设置cx和cy属性,尽管tbh最好选择一种方法并始终坚持它。
相关文章:
- 分派点击事件并保留击键修饰符
- 如何使用jquery强制一个单词更改大小写等以保留品牌
- 提交后保留下拉选择的值
- 刷新后保留对网页的更改
- 在mvc应用程序中,在回发时保留最初隐藏的文本框的隐藏或可见状态
- Flash Uploadify在调用我的MVC控制器时没有保留会话/授权
- 当设置addFromAutocompleteOnly时,剩余文本将保留在输入字段中
- 使用递归属性迭代保留属性结构
- Jquery html() 和保留元素名称
- 如何将字符串拆分为字符,但在javascript中保留空格
- 离开页面导航后保留文本区域内容
- 如何在使用JavaScript或jQuery刷新父页面后保留iframe-src
- Javascript和RegEx:拆分并保留分隔符
- 如何生成保留标点符号的简单字谜
- 如何设置类型化对象的属性,同时保留它's类型
- 关闭谷歌地图中推荐的骑行道路,但保留专用自行车道
- 使用KineticJS变换(移动/缩放/旋转)形状
- 在IndexedDB中保留空间
- 如何使网络应用程序保留信息
- 在SVG元素中保留变换