可视化svg深入理解viewport、viewbox、preserveaspectradio
直接运行此例子
深入理解svg的viewport、viewbox、preserveaspectradio实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="author" content="李可">
<title>svgviewBox的特写过程。演示动画</title>
<style>
div {
box-sizing: border-box;
}
span {
font-weight: bolder;
}
</style>
</head>
<body>
<fieldset style="width:800px;">
<legend>
<h2>viewport,viewBox,preserveAspectRatio演示-李可</h2>
</legend>
<h4>viewport: </h4>
<label for="viewportWidthNumber">width:</label>
<input type="number" id='viewportWidthNumber' value="400" oninput="updateView('#svg','width',this.value)" />
<label for="viewportHeightNumber">height:</label>
<input type="number" id='viewportHeightNumber' value="300" oninput="updateView('#svg','height',this.value)" />
<h4>viewBox: </h4>
<label for="viewBoxWidthNumber">width:</label>
<input type="number" id='viewBoxWidthNumber' value="40" oninput="updateView('#react','width',this.value)" />
<label for="viewBoxHeightNumber">height:</label>
<input type="number" id='viewBoxHeightNumber' value="30" oninput="updateView('#react','height',this.value)" />
<h4>preserveAspectRatio(align,meetOrSlice)</h4>
<select name="align" id="align" onchange="preserveAspectRadioFirst(this.value)">
<option value="none">none</option>
<option value="xMinYMin">xMinYMin</option>
<option value="xMinYMid">xMinYMid</option>
<option value="xMinYMax">xMinYMax</option>
<option value="xMidYMin">xMidYMin</option>
<option value="xMidYMid" selected>xMidYMid</option>
<option value="xMidYMax">xMidYMax</option>
<option value="xMaxYMin">xMaxYMin</option>
<option value="xMaxYMid">xMaxYMid</option>
<option value="xMaxYMax">xMaxYMax</option>
</select>
<select name="meetOrSlice" id="meetOrSlice">
<option value="meet" selected>meet</option>
<option value="slice">slice</option>
</select>
<p>viewBox,默认 0 0 width height</p>
<p>preserverAspectRadio,默认xMidYMid meet,如果align是none,meetOrSlice的值将会被忽略</p>
<div id="note" style="visibility:hidden;">
<p>按照---><span id="direction"></span>,缩放 ---> <span id="percent"></span>倍</p>
</div>
<button type="button" id="btn">运动动画</button>
</fieldset>
<div id="svg" style="margin:100px 0 0 100px;position:relative;width:400px;height:300px; background:gray;">vport
<div id="react" style="position:absolute;width:40px;height:30px;background:green;">vBox
<div id="realDiv" style="position:absolute;top:0;left:0;opacity:0.5;margin:10% 0 0 15%;width:30%;height:50%;background:red;"></div>
</div>
</div>
<script>
let updateView = (selector, attr, val) => {
document.querySelector(selector).style[attr] = val + 'px';
preserveAspectRadioFirst(align.value)
}
let preserveAspectRadioFirst = (startPosition = 'xMidYMid') => {
const svgW = viewportWidthNumber.value;
const svgH = viewportHeightNumber.value;
const reactW = viewBoxWidthNumber.value;
const reactH = viewBoxHeightNumber.value;
switch (align.value) {
case 'none':
react.style.transformOrigin = 'center center';
react.style.left = (svgW - reactW) / 2 + 'px';
react.style.top = (svgH - reactH) / 2 + 'px';
break;
case 'xMinYMin':
react.style.transformOrigin = 'left top';
react.style.left = 0 + 'px';
react.style.top = 0 + 'px';
break;
case 'xMinYMid':
react.style.transformOrigin = 'left center';
react.style.left = 0 + 'px';
react.style.top = (svgH - reactH) / 2 + 'px';
break;
case 'xMinYMax':
react.style.transformOrigin = 'left bottom';
react.style.left = 0 + 'px';
react.style.top = (svgH - reactH) + 'px';
break;
case 'xMidYMin':
react.style.transformOrigin = 'center center';
react.style.left = (svgW - reactW) / 2 + 'px';
react.style.top = 0 + 'px';
break;
case 'xMidYMid':
react.style.transformOrigin = 'center center';
react.style.left = (svgW - reactW) / 2 + 'px';
react.style.top = (svgH - reactH) / 2 + 'px';
break;
case 'xMidYMax':
react.style.transformOrigin = 'center bottom';
react.style.left = (svgW - reactW) / 2 + 'px';
react.style.top = (svgH - reactH) + 'px';
break;
case 'xMaxYMin':
react.style.transformOrigin = 'right top';
react.style.left = (svgW - reactW) + 'px';
react.style.top = 0 + 'px';
break;
case 'xMaxYMid':
react.style.transformOrigin = 'right center';
react.style.left = (svgW - reactW) + 'px';
react.style.top = (svgH - reactH) / 2 + 'px';
break;
case 'xMaxYMax':
react.style.transformOrigin = 'right bottom';
react.style.left = (svgW - reactW) + 'px';
react.style.top = (svgH - reactH) + 'px';
break;
}
}
preserveAspectRadioFirst(align.value);
let awaitFn = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
react.style.transitionDuration = '0s';
resolve()
})
})
}
let inputs = document.querySelectorAll('input');
let selects = document.querySelectorAll('select');
let disableEle = () => {
for (let i = 0; i < inputs.length; i++) {
inputs[i].setAttribute('disabled', 'disabled')
}
for (let i = 0; i < selects.length; i++) {
selects[i].setAttribute('disabled', 'disabled')
}
}
let enbledEle = () => {
for (let i = 0; i < inputs.length; i++) {
inputs[i].removeAttribute('disabled')
}
for (let i = 0; i < selects.length; i++) {
selects[i].removeAttribute('disabled')
}
}
let step = 1;
btn.addEventListener('click', async e => {
if (step % 2) {
btn.innerHTML = '初始化'
disableEle();
react.style.transition = "transform 5s";
const svgW = viewportWidthNumber.value;
const svgH = viewportHeightNumber.value;
const reactW = viewBoxWidthNumber.value;
const reactH = viewBoxHeightNumber.value;
svg.style.width = svgW + 'px';
svg.style.height = svgH + 'px';
react.style.width = reactW + 'px';
react.style.height = reactH + 'px';
let p = (reactW / reactH) / (svgW / svgH) > 1;//p>1,viewbox宽先到viewport的宽 p<1,viewbox高先到viewport的高
let s = meetOrSlice.value;
let scaleX = svgW / reactW;
let scaleY = svgH / reactH;
let scale = p ?
s == 'meet' ? scaleX : scaleY :
s == 'meet' ? scaleY : scaleX;
//note
let derector = p ?
s == 'meet' ? 'x轴' : 'y轴' :
s == 'meet' ? 'y轴' : 'x轴';
percent.innerHTML = scale;
direction.innerHTML = derector;
note.style.visibility = 'visible';
//note
react.style.transform = "scale(" + scale + ")";
} else {
note.style.visibility = 'hidden';
enbledEle()
await awaitFn()
react.style.transform = 'scale(1)'
react.style.background = 'green'
btn.innerHTML = '运动动画'
}
step++;
})
react.addEventListener('transitionend', e => {
if (e.propertyName == 'transform') {
react.style.transition = "background 5s";
react.style.background = 'transparent';
}
});
</script>
</body>
</html>
运行例子
viewport的理解
例子
这里的
viewport的宽高就是svg标签里面的width和height属性值。默认单位像素px,这里也就是400px*300px,当然可以用其他单位em rem %等等,前提你用得着~哦。然后svg的viewport就讲完了,简单吧。
<svg width="400" height="300" style="border:1px solid red">
<rect width="40" height="30" fill="green"/>
</svg>
运行图片
viewBox
重点理解,绝对不要放过的地方哦
例子1
viewBox="x y width height" 或者viewBox="x ,y,width,height" 带不带
逗号
x:初始矩形的左上点x坐标
y:初始矩形左上角y坐标
width:初始矩形宽度
height:初始矩形高度
我画三个图形,跟我先弄懂这三个
<svg width="400" height="300" style="border:1px solid red">
<rect width="40" height="30" />
</svg>
<svg width="400" height="300" viewBox="0 0 40 30" style="border:1px solid red">
<rect width="40" height="30" />
</svg><br/>
<svg width="400" height="300" viewBox="0 0 80 30" style="border:1px solid red">
<rect width="40" height="30" />
</svg>
运行图片
可视化svg深入理解viewport、viewbox、preserveaspectradio的更多相关文章
- SVG 入门——理解viewport,viewbox,preserveAspectRatio
工欲善其事必先利其器,没有真正搞懂SVG里的viewport,viewbox, preserveAspectRatio这三个属性,就很容易遇到坑,最近写项目用到svg这三个属性被我一眼就略过 ,后来发 ...
- 理解SVG中的 viewport,viewBox, preserveAspectRatio
_ 阅读目录 一:理解viewport 二:理解viewBox 三:理解 preserveAspectRatio 回到顶部 一:理解viewport 该属性表示的是SVG可见区域的大小.或者也可以叫画 ...
- 数据可视化-svg入门基础(二)
接上一篇:数据可视化-svg入门基础(一),基础一主要是介绍了svg概念,元素样式设置等. svg是(scalable vector graphic)伸缩矢量图像. 一.目录 (1)图形元素 (2)文 ...
- 理解SVG的viewport,viewBox,preserveAspectRatio
万丈高楼平地起,基础很重要. viewport 表示SVG可见区域的大小,或者可以想象成舞台大小,画布大小. <svg width="500" height="30 ...
- 深入理解viewport(转)
在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewport了,只有明白了viewport的概念以及弄清楚了跟viewport有关的meta标签的使用,才能更好地让我们的网页适配或 ...
- 深入理解viewport
这篇文章我已写成pdf,建议直接下载浏览. 链接:https://pan.baidu.com/s/1c4cwd7E 密码:jty1 <对viewport标签的理解> --版权所有 @RYZ ...
- 『cs231n』卷积神经网络的可视化与进一步理解
cs231n的第18课理解起来很吃力,听后又查了一些资料才算是勉强弄懂,所以这里贴一篇博文(根据自己理解有所修改)和原论文的翻译加深加深理解,其中原论文翻译比博文更容易理解,但是太长,而博文是业者而非 ...
- HTML-HTML5+CSS3权威指南阅读(五、深入理解viewport)
1.手机浏览器与桌面浏览器的不同 现在手机浏览器的显示分辨率与桌面浏览器差不多,但是手机的尺寸比电脑要小很多.一个没做过响应式处理的网站,在手机和电脑上显示完全一样的内容, 不可避免的会出现字体被缩小 ...
- 通透理解viewport
摘自:https://blog.csdn.net/u014787301/article/details/44466697 在移动设备上进行网页的重构或开发,首先得搞明白的就是移动设备上的viewpor ...
随机推荐
- 腾讯云cos对象在线显示
问题 前端使用了一张cos的图片,但是无法显示图片,使用的是cdn的加速域名地址. 对比:使用服务器的直接域名是可以显示的. 两者地址直接访问时,一者在线显示,一者直接下载到本地. 原因: 使用默认提 ...
- C 标识符, 数据存储形式(原码,反码,补码)
一. 标识符 第一个字母必须是英文字母或下划线 二. 数据存储形式(补码存储) 最高位是符号位 ---- 0表示整数 ; 1 表示负数 1. 正数:原码 = 反码 = 补码 例子 : (10) 原码 ...
- js for循环中定义clike事件由于闭包导致的循环变量获取不到的问题
在网上找的 记下来以备不时之需 案例; 本人有一个数组按钮 循环数组按钮 给每个按钮添加click事件 原本以为搞定但是出现了 每个按钮都是数组最后的方法 然后查找问题 发现onclike事件中的i ...
- DevExpress gridview获取单元格坐标(转)
private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventA ...
- 2019年3月更新 技术分享 WPF基本界面制作
1.制作流程1.在vs中建立一个wpf程序2.建立一个主页面(.cs)(注:C#程序每一个页面都由两个文件构成一个xaml一个cs,一个前端文件一个后台文件)3.在主页面中添加按钮,按钮中嵌入图片,这 ...
- Centos6两个镜像文件的合并方法
1.相关目录: /mnt/dvd1和/mnt/dvd2 用于挂载 Centos 镜像 /mnt/dvd3 合并后的镜像文件 /mnt/iso ISO储存 mkdir -p /mnt/dvd1 /mnt ...
- ASP.NET CORE 3 安装遇到的问题
最近在研究 ASP.NET CORE, visualstudio2019 也已正式发布,本以为安装vs2019后就默认支持asp.net core 3,谁知是不支持的,需单独安装net core 3及 ...
- RAMOS和SSD对比
http://bbs.pcbeta.com/forum.php?mod=redirect&goto=findpost&ptid=1786284&pid=48341400RAMO ...
- 搭建 Jest+ Enzyme 测试环境
1.为什么要使用单元测试工具? 因为代码之间的相互调用关系,又希望测试过程单元相互独立,又能正常运行,这就需要我们对被测函数的依赖函数和环境进行mock,在测试数据输入.测试执行和测试结果检查方面存在 ...
- 刘志梅 2017710101152《面向对象程序设计(java)》 第十周学习总结
实验十 泛型程序设计技术 实验时间 2018-11-1 1.实验目的与要求 (1)泛型程序设计:意味着编写的代码可以被很多不同类型的对象所重用.(ArrayList类可以聚集任何类型的对象) 如果在 ...