如何在调整窗口大小时设置svg以更改位置? [英] How to setup svg to change position when resizing the window?
问题描述
在浏览器窗口中,我有一个包含图像的svg。
我也在这个页面放了一些圈子。
当我调整窗口大小时,图片的大小会正确调整,但圆圈只能保持其绝对位置。
设置图片的最佳方法是什么?
如果可能的话,这些圈子不应该调整大小,而是改变它们的位置。
<!DOCTYPE html>
< html>
< head>
< meta http-equiv =content-typecontent =text / html; charset = UTF-8>
< meta name =robotscontent =noindex,nofollow>
< meta name =googlebotcontent =noindex,nofollow>
< style>
html,body {padding:0px;保证金:0像素;高度:100%;宽度:100%;}
< / style>
< script type =text / javascriptsrc =http://d3js.org/d3.v3.min.js>< / script>
< title>测试< / title>
< script type ='text / javascript'> //<![CDATA [
window.onload = function()
{
函数click()
{
//忽略click事件,如果被抑制
if(d3.event.defaultPrevented)return;
//提取点击位置
var point = d3.mouse(this)
,p = {x:point [0],y:point [1]};
//追加组
var newGroup = d3.select(svg)。append(g)
.attr(transform, translate(+ px +,+ py +))
.attr(drgg,)
.style(cursor,pointer)
.on(mouseup,selremove)
.call(drag);
//追加圆
var newCircle = newGroup.append(circle)
.attr(r,25)
.attr( class,dot)
.style(stroke,#999999)
.style(fill,#66B132)
.attr(opacity ,0.8);
//追加文本
var newText = newGroup.append(text)
.text(43)
.style(fill, #FFFFFF)
.style(font-family,Arial)
.style(font-size,24px)
.style(text-anchor ,middle)
.style(alignment-baseline,central)
.style(readonly,true);
$ b //创建SVG
var svg = d3.select(body)。append(svg)
.attr(width,100%)
.attr(height,100%)
.on(click,click);
//为SVG添加背景
svg.append(rect)
.attr(width,100%)
.attr (高度,100%)
.style(stroke,#999999)
.style(fill,#F6F6F6)
//添加背景图片
var pPic = d3.select(body)。select(svg)。append(image)
.attr(opacity,1.0)
.attr(width,100%)
.attr(height,100%)
.attr(preserveAspectRatio,xMidyMid)
.attr(xlink:href,https://m.bmw.de/content/dam/bmw/common/all-models/m-series/x6m/2014/model-card/X6-M-F86_ModelCard。 png)
//移动或删除
函数selremove(){
if(d3.select(this).attr(drgg)==)
{
d3.select(this).remove() ;
}
else
{
d3.select(this).attr(drgg,);
函数showinfo(){
//d3.select(this).attr(\"fill,#000000);
var point = d3.mouse(this)
,p = {x:point [0],y:point [1]};
$ b $ var newRect = svg.append(rectangle)
.attr(transform,translate(+ px +,+ py +))
.attr(width,25)
.attr(height,25)
.style(stroke,#999999)
.style( fill,#FFFA83)
.attr(opacity,1.0);
}
//定义拖曳元素
var drag = d3.behavior.drag()
.on(drag,dragmove);
函数dragmove()
{
var x = d3.event.x;
var y = d3.event.y;
d3.select(this)
.attr(transform,translate(+ x +,+ y +))
.attr( drgg,1);
}
} //]]>
< / script>
< / head>
< body>
< script>
//告诉嵌入父框架内容的高度
if(window.parent&& window.parent.parent){
window.parent.parent.postMessage([ resultsFrame,{
height:document.body.getBoundingClientRect()。height,
slug:None
}],*)
}
< ; /脚本>
< / body>
< / html>
我首先想到这可以用相对单位来实现,但SVG纵横比的变化让你进入了炎热的水域。所以最好的方法似乎是将SVG viewBox固定到原始图像尺寸。这些需要事先知道,因为SVGImageElement无法从图像源本身提取它们。
支付的代价是叠加圈必须是每次窗口大小调整时调整大小。
这个例子并不涉及拖动功能。
//一个事件计数器
var counter = 0;
//图片元数据
var pData = {
url:https://m.bmw.de/content/dam/bmw/common/all-models/m -series / x6m / 2014 / model-card / X6-M-F86_ModelCard.png,
width:890,
height:501
}
//用本地图像大小的viewBox创建SVG
var svg = d3.select(body)。append(svg)
.attr(xmlns:xlink,http:// www .w3.org / 1999 / xlink)
.attr(width,100%)
.attr(height,100%)
.attr(' viewBox',0 0+ pData.width ++ pData。height)
.attr(preserveAspectRatio,xMidyMid)
.on(click,click);
var defs = svg.append(defs);
$ b $ //添加背景图片
var pPic = d3.select(body)。select(svg)。append(image)
.attr (width,100%)
.attr(height,100%)
.attr(xlink:href,pData.url)
函数click(){
//忽略click事件,如果被抑制
if(d3.event.defaultPrevented)return;
//提取相对于SVG的点击位置
var point = d3.mouse(this);
//获得SVG缩放
var ctm = svg.node()。getScreenCTM(),
scale =scale(+(1 / ctm.a)+,+( 1 / ctm.d)+);
//唯一ID
var id =dot+ counter ++;
//在屏幕外追加
var newGroup = defs.append(g)
.attr(id,id)
.attr(转化,规模);
//追加圆
var newCircle = newGroup.append(circle)
.attr(r,25)
.attr( class,dot)
.style(stroke,#999999)
.style(fill,#66B132)
.attr(opacity ,0.8);
//追加文本
var newText = newGroup.append(text)
.text(43)
.style(fill, #FFFFFF)
.style(font-family,Arial)
.style(font-size,24px)
.style(text-anchor ,middle)
.style(alignment-baseline,central)
.style(readonly,true);
//使用新视口进行间接渲染
svg.append(use)
.attr(xlink:href,#+ id)
.attr(x,point [0])
.attr(y,point [1]);
}
//在窗口上调整组大小resize
var resize;
window.addEventListener(resize,function(){
clearTimeout(resize);
resize = setTimeout(function(){
var ctm = svg.node()。 getScreenCTM();
//在重定位之前选择所有组
defs.selectAll('g')。attr(transform,scale(+(1 / ctm.a)+ ,+(1 / ctm.d)+));
},100);
});
In a browser window I have an svg containing an image. I also put some circles in this page. When I resize the window, the image resizes correct but the circles just stay on their absolute position.
What is the best way to set this up? If possible, the circles should not resize but change their position.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
<style>
html,body{padding:0px; margin:0px; height:100%; width:100%;}
</style>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<title>Test</title>
<script type='text/javascript'>//<![CDATA[
window.onload=function()
{
function click()
{
// Ignore the click event if it was suppressed
if (d3.event.defaultPrevented) return;
// Extract the click location
var point = d3.mouse(this)
, p = {x: point[0], y: point[1] };
//Append the group
var newGroup = d3.select("svg").append("g")
.attr("transform", "translate(" + p.x + "," + p.y + ")")
.attr("drgg", "")
.style("cursor", "pointer")
.on("mouseup", selremove)
.call(drag);
//Append the circle
var newCircle = newGroup.append("circle")
.attr("r", "25")
.attr("class", "dot")
.style("stroke", "#999999")
.style("fill", "#66B132")
.attr("opacity", 0.8);
//Append the text
var newText = newGroup.append("text")
.text("43")
.style("fill", "#FFFFFF")
.style("font-family", "Arial")
.style("font-size", "24px")
.style("text-anchor", "middle")
.style("alignment-baseline", "central")
.style("readonly", "true");
}
//Create the SVG
var svg = d3.select("body").append("svg")
.attr("width", "100%")
.attr("height", "100%")
.on("click", click);
//Add a background to the SVG
svg.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.style("stroke", "#999999")
.style("fill", "#F6F6F6")
//Add a Background-Picture
var pPic = d3.select("body").select("svg").append("image")
.attr("opacity", 1.0)
.attr("width", "100%")
.attr("height", "100%")
.attr("preserveAspectRatio", "xMidyMid")
.attr("xlink:href", "https://m.bmw.de/content/dam/bmw/common/all-models/m-series/x6m/2014/model-card/X6-M-F86_ModelCard.png")
//Move or delete
function selremove() {
if (d3.select(this).attr("drgg") == "")
{
d3.select(this).remove();
}
else
{
d3.select(this).attr("drgg", "");
}
}
function showinfo() {
//d3.select(this).attr("fill", "#000000");
var point = d3.mouse(this)
, p = {x: point[0], y: point[1] };
var newRect = svg.append("rectangle")
.attr("transform", "translate(" + p.x + "," + p.y + ")")
.attr("width", "25")
.attr("height", "25")
.style("stroke", "#999999")
.style("fill", "#FFFA83")
.attr("opacity", 1.0);
}
// Define drag beavior
var drag = d3.behavior.drag()
.on("drag", dragmove);
function dragmove()
{
var x = d3.event.x;
var y = d3.event.y;
d3.select(this)
.attr("transform", "translate(" + x + "," + y + ")")
.attr("drgg", "1");
}
}//]]>
</script>
</head>
<body>
<script>
// tell the embed parent frame the height of the content
if (window.parent && window.parent.parent){
window.parent.parent.postMessage(["resultsFrame", {
height: document.body.getBoundingClientRect().height,
slug: "None"
}], "*")
}
</script>
</body>
</html>
I first thought this could be achieved with relative units, but the changing aspect ratio of the SVG gets you into hot waters. So the best approach seems to come with clamping the SVG viewBox to the original image dimensions. These need to be known beforehand, as SVGImageElement is not able to extract them from the image source itself.
The price to pay for this is that the overlay circles have to be resized every time the window is resized.
This example does not concern itself with the drag functionality.
//an event counter
var counter = 0;
//image metadata
var pData = {
url: "https://m.bmw.de/content/dam/bmw/common/all-models/m-series/x6m/2014/model-card/X6-M-F86_ModelCard.png",
width: 890,
height: 501
}
//Create the SVG with viewBox at native image size
var svg = d3.select("body").append("svg")
.attr("xmlns:xlink", "http://www.w3.org/1999/xlink")
.attr("width", "100%")
.attr("height", "100%")
.attr('viewBox', "0 0 " + pData.width + " " + pData. height)
.attr("preserveAspectRatio", "xMidyMid")
.on("click", click);
var defs = svg.append("defs");
//Add a Background-Picture
var pPic = d3.select("body").select("svg").append("image")
.attr("width", "100%")
.attr("height", "100%")
.attr("xlink:href", pData.url)
function click() {
// Ignore the click event if it was suppressed
if (d3.event.defaultPrevented) return;
// Extract the click location relative to SVG
var point = d3.mouse(this);
// get SVG scaling
var ctm = svg.node().getScreenCTM(),
scale = "scale(" + (1 / ctm.a) + "," + (1 / ctm.d) + ")";
// Unique id
var id = "dot" + counter++;
//Append the group offscreen
var newGroup = defs.append("g")
.attr("id", id)
.attr("transform", scale);
//Append the circle
var newCircle = newGroup.append("circle")
.attr("r", "25")
.attr("class", "dot")
.style("stroke", "#999999")
.style("fill", "#66B132")
.attr("opacity", 0.8);
//Append the text
var newText = newGroup.append("text")
.text("43")
.style("fill", "#FFFFFF")
.style("font-family", "Arial")
.style("font-size", "24px")
.style("text-anchor", "middle")
.style("alignment-baseline", "central")
.style("readonly", "true");
// indirect rendering with a new viewport
svg.append("use")
.attr("xlink:href", "#" + id)
.attr("x", point[0])
.attr("y", point[1]);
}
// adjust group sizes on window resize
var resize;
window.addEventListener("resize", function() {
clearTimeout(resize);
resize = setTimeout(function () {
var ctm = svg.node().getScreenCTM();
// select all groups before they are repositioned
defs.selectAll('g').attr("transform", "scale(" + (1 / ctm.a) + "," + (1 / ctm.d) + ")");
}, 100);
});
这篇关于如何在调整窗口大小时设置svg以更改位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!