svg

102 阅读3分钟

svg屏幕缩放适配:规则:保持宽高比不变,按照父元素盒子大小来缩放

假设整个右侧的尺寸:1200*800 
<svg
     xmlns="http://www.w3.org/2000/svg"
     preserveAspectRatio="xMidYMid meet"
     style="width: 100%; height: 100%"
     viewBox="0 0 1200 800"
     ref="svgDom"
 > </svg>

声明全局变量:
var svgSize = {
    w: 1200,
    h: 800,
    scale: 1,
    update() {
        var container = document.querySelector(".container");//svg外层盒子
        var svgWidth = container.clientWidth;
        var svgHeight = container.clientHeight;
        if (svgSize.w / svgSize.h < svgWidth / svgHeight) {//保持宽高比
            // h的减小更多的情况
            svgSize.scale = svgHeight / svgSize.h;
        } else {
            svgSize.scale = svgWidth / svgSize.w;
        }
    },
};
const svgDom = ref(null);
onMounted(async()=>{
    svgDom.value.setAttribute("viewBox", `0 0 ${svgSize.w} ${svgSize.h}`);
    svgSize.update();
})

window.addEventListener('resize',()=>{
    svgSize.update();
})

js操作svg元素

// 动态生成svg标签
function createTag(tag, objAttr) {
    var oTag = document.createElementNS("<http://www.w3.org/2000/svg>", tag);
    for (var attr in objAttr) {
    oTag.setAttribute(attr, objAttr\[attr]);
    }
    return oTag;
}
var oImage = createTag("image", {
    x: `${x+w/2}`,
    y: `${y+h/2}`,
    width:"20",
    height:"20",
    preserveAspectRatio: "none",
    'vector-effect': "non-scaling-stroke",
    href:pic1,//html中写这个属性要写成xlink:href=".png"
    q:99,//这是自定义属性
});

//动态设置path路径的d属性  
A弧线解释(x:半径,y:半径,角度(一般圆的是0,椭圆会变化),弧长(0小弧1大弧),方向(0逆时针),终点x,终点y)
let arr= \[]
let d = 3
let h = 3
let startStr = `M${d} ${h}`
let endStr = `v${h} A${25/2+d*2+10} ${25/2+d*2} 0 0 1 ${360-d*2} 550v-${150+h*40}`
arr.forEach((node,index)=>{
if(index == 0){
    //如果此选项是不需要设置的,则return
    return;
}
let cx = node.getAttribute("cx")
let cy = node.getAttribute("cy")
if(index == 1){
    startStr+=`L${cx} ${cy}`;
}else{
    startStr+=`L ${cx} ${cy}`;
}
})
startStr += endStr
startStr +='Z'
path.setAttribute("d", startStr)

特殊标签:

defs:里面的dom元素只有调用时才会被使用

案例1:svg中引入箭头:
定义箭头:
<defs>
    <marker
         id="Triangle1"
         viewBox="0 0 10 10"
         refX="5"
         refY="5"
         markerWidth="6"
         markerHeight="6"
         orient="auto"
         fill="#0033CC"
         > 
         <path d="M 0 0 L 10 5 L 0 10 z" /> 
     </marker> 
     <marker
         id="Triangle2"
         viewBox="0 0 10 10"
         refX="5"
         refY="5"
         markerWidth="6"
         markerHeight="6"
         orient="90"
         fill="#0033CC"
     > 
         <path d="M 0 0 L 10 5 L 0 10 z" /> 
     </marker> 
 </defs>
使用箭头:通过id引入 
<path
     d="M50 200 50 55"
     stroke-dasharray=" 9 1"
     stroke="#0033CC"
     stroke-width="2"
     fill="none"
     marker-end="url(#Triangle1)"
     marker-start="url(#Triangle2)"
 ></path>
defs:渐变效果
定义渐变: 
<defs> 
    <radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%"> 
        <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:0" /> 
        <stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" /> 
    </radialGradient> 
</defs>
使用渐变:通过url引入 
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
defs:填充效果:设置了patternUnits:"userSpaceOnUse",就可以设置pattern的width和height不按父元素的百分比来作为单位;
定义填充:
<defs> 
    <pattern id="grid" x="100" y="100" width="0.2" height="0.2" patternUnits="objextBoundingBox">
        <circle cx="10" cy="10" r="5" fill="red"></circle> 
        <polygon points="30 10 60 50 0 50" fill="green"></polygon> 
    </pattern> 
</defs>
使用填充:通过url引入 
<rect x="100" y="100" width="400" height="300" fill="url(#grid)" stroke="blue"></rect>
defs:发光效果:
定义发光: 
<defs> 
    <filter id="faguang" x="-120%" y="-120%" width="400%" height="400%"> 
        <feOffset result="offOut" in="SourceGraphic" dx="0" dy="0"></feOffset>
        <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10"></feGaussianBlur> 
        <feBlend in="SourceGraphic" in2="blurOut" mode="multiply"></feBlend>
    </filter> 
</defs>
使用发光:通过url引入 
<rect x="10" y="10" width="100" height="100" fill="#ccc" filter="url(#faguang)"></rect>

特殊标签:use:克隆的作用:用href="#a"引入

特殊标签:animate:普通属性的动画(x属性,从0,到100,持续3s,无限次循环),可以写多个

    `<rect x="10" y="10" width="100" height="100"> 
            <animate attributeName="x" from="0" to="10" dur="3" repeatCount="definite"/> 
    </rect>`

特殊标签:animateTransform:transform属性的动画(rotate,从0,到360,第0s开始动画,持续3s,无限次循环)

<rect x="10" y="10" width="100" height="100"> <animateTransform attributeName="transform" type="rotate" from="0 200 200" to="360 200 200"  begin="0s" dur="3" repeatCount="definite"/> </rect>

特殊标签:animateMotion:让某个元素沿着固定的路径做运动

<rect x="10" y="10" width="100" height="100"></rect> 
<animateMotion path="M0 0 L300 300"  begin="0s" dur="3"/>

特殊标签:title:用于加提示框

<rect x="10" y="10" width="100" height="100"> 
    <title>hello</title> 
</rect>

旋转平移缩放:

旋转平移缩放都可以累加:
transform="translate(10 1) translate(10 1)"
等价于
transform="translate(20 2)"
旋转中心设置:默认中心是整个svg的左上角
1.属性后面加方括号
rotate(90,[x y]);//旋转90°
2.设置元素的css:

svg的css属性是区别于html标签的,可以设置fill等,不能设置backgroung等,但svg最外层盒子是html;

    transform-box:fill-box;//以当前盒子作为参考盒子
    transform-origin:center center;//设置旋转中心
缩放中心点设置:
1.手动改变缩放前后的相差位置:x = x+width/2 y=y+height/2
<rect x="110" y="100" width="120" height="90" data-svg="gltransform_tcwanimate" transform="translate(170 145) scale(1.5, 1.5) translate(-170 -145)"> 
</rect>
2.设置元素的css:svg的css属性是区别于html标签的,可以设置fill等,不能设置backgroung等,但svg最外层盒子是html;
transform-box:fill-box;//以当前盒子作为参考盒子
transform-origin:center center;//设置旋转中心

tips:

填充方式:Fill-rule:evenodd(一个填充一个不填),默认都填充,给多边形设置不同区域填充不同
foreignObject标签:可以内嵌html和支持css样式
<foreignObject width="120" height="50">
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>文字。</p>
      </body>
    </foreignObject>
```
```

###### 文字居中:左右:"text-anchor": "middle",上下居中:文字大小/2-2+y=文字上下距离

###### 清空子元素:父盒子.innerHTML = "";

###### 坐标转换:svg=>平面直角坐标系:X=x-w/2;Y=-y+h/2

###### 设置虚线:stroke-dasharray="3 2"//实线宽度 空白宽度;stroke-dashoffset=//虚线偏移量

###### 与路径上起始点距离为s的点坐标:getPointAtlength(s)

###### 获得路径总长度:getTotalLength()

###### 运动路径:offset-path

###### 元素在路径上运动的距离:offset-distance

###### SVG文件的导入方式:

    1.<img src="...svg">
    2.有dom结构<embed src="...svg"/>
    3.有结构<iframe src="...svg"/>
    4.style="background-image:url(...svg);"

# text更多设置:<https://blog.csdn.net/weixin_40779234/article/details/113701444>