- getAttributesNs/setAttributesNs
- element.setAttributeNS(namespace,name,value)
namespace 是指定属性的命名空间的一个字符串.
name 是标识要设置的属性的一个字符串.
value 是新属性的所需字符串值.
添加 / 或者查询一个新属性或更改具有给定命名空间和名称的一个属性的值.
setAttribute() 是 DOM 1 函数. setAttributeNS() 是 DOM 2 函数
果属性没有定义的名称空间前缀, 则第一个参数必须为 null. 您可以使用 setAttribute(), 但是为了保持一致性, 建议坚持使用 setAttributeNS()
应用 demo
程序思路
首先我们看看代码映射
- // 按下
- box.onmousedown = function (event) {
- console.log(1);
- // 移动
- box.onmousemove=function () {
- console.log(2);
- }
- // 抬起
- box.onmouseup=function () {
- console.log(3);
- }
- }
通过 point 拿到所有 circle 图形的原点
line 拿到直线的 dom 和 path 的 dom
限制坐标的范围, 由于 circle 的半径有一定长度, 所以减去 5 做一定的限制
- maxX = container.offsetWidth - 5
- maxY = container.offsetHeight - 5,
- // 鼠标范围限制
- function PointM(x, y) {
- return {
- x: Math.max(0, Math.min(maxX, x)),
- y: Math.max(0, Math.min(maxY, y))
- }
- }
- m = PointM(e.pageX, e.pageY);
当鼠标点在 path 上可以通过 fill 进行切换背景颜色
+circle[i].getAttributeNS(null, 'cx')
要知道我们通过 getAttributeNS 拿到的是字符串所以要进行转化
['p1', 'p2', 'c1', 'c2'].includes(id)
是为了保证按在是个点上面, 然后后面的 id 容易报错
整体的逻辑就是
鼠标按下开始的时候, 记录当前的坐标, 拿到点击的那个 dom
后续鼠标移动的时候, 当前的坐标 - 开始的坐标的差值 = 本来应该指向的坐标
并且移动的时候要设置一定的范围, 以便更新点不能离开当前的范围
鼠标离开的时候, 关闭移动 / 松开的事件
- <!doctype html>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>
- Document
- </title>
- <style>
- * { margin: 0; padding: 0; } #container { width: 100%; height: 500px;
- background-color: #fff; margin: 0 auto; text-align: center; } path { stroke-width:
- 8; stroke: #1E1935; stroke-linecap: round; fill: none; } circle { stroke-width:
- 2; stroke: #ef2d56; fill: #fff; } circle:hover { fill: #ef2d56; cursor:
- move; } line { stroke-width: 1; stroke: #999; stroke-linecap: round; stroke-dasharray:
- 5, 3; } path { stroke-width: 2; stroke: #1E1935; stroke-linecap: round;
- /* fill: none; */ } path.fill { fill: #1E1935 }
- </style>
- </head>
- <body>
- <div style="text-align: center">
- <pre id="code" style="font-size: 40px;font-family: Consolas;">
- code
- </pre>
- </div>
- <div id="container" class="C">
- <svg id="svg" viewBox="0 0 499 499" width="500" height="500" preserveAspectRatio="xMidYMid meet">
- <g id="main">
- <circle id="p1" cx="100" cy="250" r="16" />
- <circle id="p2" cx="400" cy="250" r="16" />
- <circle id="c1" cx="100" cy="100" r="8" />
- <circle id="c2" cx="400" cy="100" r="8" />
- <line id="l1" x1="100" y1="250" x2="100" y2="100" />
- <line id="l2" x1="400" y1="250" x2="400" y2="100" />
- <path id="path" d="M100,250 C100,100 400,100 400,250" />
- </g>
- </svg>
- </div>
- <script>
- let svg = document.getElementById('svg'),
- container = document.getElementById('container') let point = {},
- line = {},
- maxX = container.offsetWidth - 5,
- maxY = container.offsetHeight - 5,
- fill = false,
- code = document.getElementById('code'),
- // 状态
- drap = null,
- dPonit;
- function init() {
- let circle = svg.getElementsByTagName('circle');
- for (let i = 0; i < circle.length; i++) {
- point[circle[i].getAttributeNS(null, 'id')] = {
- x: +circle[i].getAttributeNS(null, 'cx'),
- y: +circle[i].getAttributeNS(null, 'cy'),
- }
- }
- line.l1 = svg.getElementById('l1') line.l2 = svg.getElementById('l2') line.path = svg.getElementById('path') svg.onmousedown = document.onmousemove = document.onmouseup = Drag svg.ontouchstart = document.ontouchmove = document.ontouchend = Drag
- }
- // 鼠标范围限制
- function PointM(x, y) {
- return {
- x: Math.max(0, Math.min(maxX, x)),
- y: Math.max(0, Math.min(maxY, y))
- }
- }
- function Drag(e) {
- e.stopPropagation() let t = e.target,
- id = t.id,
- et = e.type,
- m = PointM(e.pageX, e.pageY);
- // 鼠标按在 path 区域
- if (!drap && id === 'path' && et === 'mousedown') {
- fill = !fill;
- t.setAttributeNS(null, 'class', (fill ? 'fill': '')) DragGet();
- }
- // 鼠标按在开始
- // typeof(point[id]!==undefined) 意思就是要按在这几个点上
- if (!drap && ['p1', 'p2', 'c1', 'c2'].includes(id) && (et === 'mousedown' || et === 'touchstart')) {
- drap = t;
- dPonit = m
- }
- // 移动的时候
- if (drap && ['p1', 'p2', 'c1', 'c2'].includes(id) && (et === 'mousemove' || et === 'touchmove')) {
- console.log(id);
- // 当前的坐标 - 开始的坐标等于差值
- point[id].x += m.x - dPonit.x;
- point[id].y += m.y - dPonit.y;
- if (point[id].x < maxX && point[id].y < maxY) {
- id = drap.id;
- dPonit = m;
- drap.setAttributeNS(null, "cx", point[id].x);
- drap.setAttributeNS(null, "cy", point[id].y);
- }
- DragGet()
- }
- // 松开的时候
- if (drap && (et === "mouseup" || et === "touchend")) {
- drap = null;
- }
- }
- // 更新数据
- function DragGet() {
- // line1
- line.l1.setAttributeNS(null, 'x1', point.p1.x);
- line.l1.setAttributeNS(null, 'y1', point.p1.y);
- line.l1.setAttributeNS(null, 'x2', point.c1.x);
- line.l1.setAttributeNS(null, 'y2', point.c1.y);
- // line2
- line.l2.setAttributeNS(null, 'x1', point.p2.x) line.l2.setAttributeNS(null, 'y1', point.p2.y) line.l2.setAttributeNS(null, 'x2', point.c2.x) line.l2.setAttributeNS(null, 'y2', point.c2.y) let d = `M $ {
- point.p1.x
- },
- $ {
- point.p1.y
- }
- C $ {
- point.c1.x
- },
- $ {
- point.c1.y
- }
- $ {
- point.c2.x
- },
- $ {
- point.c2.y
- }
- $ {
- point.p2.x
- },
- $ {
- point.p2.y
- }
- $ {
- fill ? 'Z': ''
- }`line.path.setAttributeNS(null, 'd', d) code.textContent = d;
- }
- init()
- </script>
- </body>
- </HTML>
来源: https://www.cnblogs.com/fangdongdemao/p/13890948.html