如何在调整窗口大小时设置svg以更改位置?
问题描述:
在浏览器窗口中,我有一个包含图像的svg。 我也在这个页面上放了一些圈子。 当我调整窗口大小时,图像调整大小正确,但圆圈仍保持其绝对位置。如何在调整窗口大小时设置svg以更改位置?
设置它的最佳方法是什么? 如果可能,圈子不应调整大小,而应改变其位置。
<!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>
答
我首先想到这可以用相对单位来实现,但SVG的纵横比变化会让你进入热水。所以最好的方法似乎是将SVG viewBox固定到原始图像尺寸。这些需要事先知道,因为SVGImageElement不能从图像源本身提取它们。
为此付出的代价是每次调整窗口大小时都必须调整叠加圈子。
本示例不涉及拖动功能。
//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);
});
看来你的代码有问题。但是,除非我们有[可以重现问题的代码或信息](// stackoverflow.com/help/mcve),否则我们无能为力。否则,我们只是盲目猜测。 –
请在您的问题中添加[mcve] –