简体   繁体   中英

How to setup svg to change position when resizing the window?

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);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM