如何在调整窗口大小时设置svg以更改位置? [英] How to setup svg to change position when resizing the window?

查看:83
本文介绍了如何在调整窗口大小时设置svg以更改位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在浏览器窗口中,我有一个包含图像的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆