如何在调整窗口大小时设置svg来改变位置?

时间:2017-08-30 14:09:31

标签: javascript html d3.js 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>

1 个答案:

答案 0 :(得分:1)

我首先想到的是这可以用相对单位来实现,但是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);
});