react实现svg钢笔路径编辑调整效果代码
代码语言:html
所属分类:其他
代码描述:react实现svg钢笔路径编辑调整效果代码
代码标签: react 实现 svg 钢笔 路径 编辑 调整
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> @import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600); :root { --ad-Color-prim: #111; --ad-Color-sec: #00E676; --ad-Color-del: #E53935; } html { font-size: 16px; font-family: "Open Sans", sans-serif; } html, body { height: 100%; } .ad-App { height: 100%; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } /* main layout */ .ad-Container { height: 100%; width: 100%; display: -webkit-box; display: -ms-flexbox; display: flex; background: #fff; } .ad-Container-main { height: 100%; -webkit-box-flex: 1; -ms-flex: 1; flex: 1; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; } .ad-Container-svg { height: 100%; -webkit-box-flex: 1; -ms-flex: 1; flex: 1; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; background: #f3f3f3; } .ad-Container-controls { overflow: hidden; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -ms-flex-direction: column; flex-direction: column; height: 100%; width: 20rem; background: #111; background: var(--ad-Color-prim); } .ad-Container-controls ::-webkit-scrollbar { width: 6px; } .ad-Container-controls ::-webkit-scrollbar-thumb { border-radius: 30px; background: rgba(255, 255, 255, .3); } .ad-Foot { padding: 1.5rem 2rem; display: -webkit-box; display: -ms-flexbox; display: flex; background: #fff; border-top: 2px solid #eee; } .ad-Foot-list { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } .ad-Foot-item { text-transform: uppercase; font-size: .7rem; color: #111; color: var(--ad-Color-prim); } .ad-Foot-item + .ad-Foot-item { margin-top: .5rem; } .ad-Foot-highlight { padding-bottom: .04rem; border-bottom: 2px solid #00E676; border-bottom: 2px solid var(--ad-Color-sec); font-weight: bold; } .ad-Foot-meta { margin-left: 2rem; text-align: right; line-height: 1.4; font-size: .7rem; color: #111; color: var(--ad-Color-prim); } .ad-Foot-meta a { text-decoration: underline; color: #111; color: var(--ad-Color-prim); } .ad-SVG { display: block; background: #fff; border-radius: 4px; } .ad-Grid { fill: none; stroke: #eee; stroke-width: 1px; } .ad-Grid.is-hidden { opacity: 0; } .ad-Path { fill: none; stroke: #555; stroke-width: 4px; stroke-linecap: round; } .ad-Point { cursor: pointer; fill: #fff; stroke: #555; stroke-width: 5px; -webkit-transition: fill .2s; -o-transition: fill .2s; transition: fill .2s; } .ad-Point:hover, .ad-PointGroup.is-active .ad-Point { fill: #00E676; fill: var(--ad-Color-sec); } .ad-PointGroup--first .ad-Point { stroke: #00E676; stroke: var(--ad-Color-sec); } .ad-Anchor { opacity: .5; } .ad-PointGroup.is-active .ad-Anchor { opacity: 1; } .ad-Anchor-point { cursor: pointer; fill: #fff; stroke: #888; stroke-width: 5px; } .ad-Anchor-line { stroke: #888; stroke-width: 1px; stroke-dasharray: 5 5; } /* controls on the right */ .ad-Controls { overflow: auto; -webkit-box-flex: 1; -ms-flex: 1; flex: 1; padding: 2rem; } .ad-Controls :first-child { margin-top: 0; } .ad-Controls-title { margin: 3rem 0 1.5rem; font-size: .8rem; font-weight: bold; color: #fff; } .ad-Controls-container { display: -webkit-box; display: -ms-flexbox; display: flex; } .ad-Controls-container + .ad-Controls-container { margin-top: 1.5rem; } .ad-Control { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } .ad-Control-label { display: block; margin-bottom: .5rem; text-transform: uppercase; font-size: .6rem; font-weight: bold; color: color(#111 l(+75%)); color: color(var(--ad-Color-prim) l(+75%)); } .ad-Result { height: 5rem; padding: 1.4rem 1.6rem; background: #111; background: var(--ad-Color-prim); -webkit-box-shadow: 0 -5px 10px rgba(0, 0, 0, .4); box-shadow: 0 -5px 10px rgba(0, 0, 0, .4); } .ad-Result-textarea { height: 100%; width: 100%; resize: none; border: none; background: none; text-transform: uppercase; font-family: "Open Sans", sans-serif; font-size: .7rem; font-weight: bold; line-height: 1.8; color: #fff; } .ad-Result-textarea:focus { outline: 0; } /* control elements */ .ad-Button { padding: .8rem 1.4rem; background: #00E676; background: var(--ad-Color-sec); border: none; border-radius: 50px; cursor: pointer; -webkit-transition: background .2s; -o-transition: background .2s; transition: background .2s; text-transform: uppercase; font-family: "Open Sans", sans-serif; font-weight: bold; font-size: .6rem; letter-spacing: .08rem; color: #fff; } .ad-Button:focus, .ad-Button:hover { outline: 0; background: color(#00E676 l(+5%)); background: color(var(--ad-Color-sec) l(+5%)); } .ad-Button--delete { background: #E53935; background: var(--ad-Color-del); } .ad-Button--delete:focus, .ad-Button--delete:hover { background: color(#E53935 l(+5%)); background: color(var(--ad-Color-del) l(+5%)); } .ad-Button--reset { background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); } .ad-Button--reset:focus, .ad-Button--reset:hover { background: color(#111 l(+15%)); background: color(var(--ad-Color-prim) l(+15%)); } .ad-Text { height: 18px; width: 2rem; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); border: none; border-radius: 4px; text-align: center; font-family: "Open Sans", sans-serif; font-size: .6rem; color: #fff; } .ad-Text:focus { outline: 0; background: color(#111 l(+20%)); background: color(var(--ad-Color-prim) l(+20%)); } .ad-Checkbox-input { display: none; } .ad-Checkbox-fake { position: relative; height: 14px; width: 2rem; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); border-radius: 30px; } .ad-Checkbox-fake::after { content: ""; -webkit-box-sizing: border-box; box-sizing: border-box; display: block; position: absolute; top: -2px; left: 0; height: 18px; width: 18px; cursor: pointer; border: 4px solid #fff; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); border-radius: 50%; } .ad-Checkbox-input:checked + .ad-Checkbox-fake::after { left: auto; right: 0; border-color: #00E676; border-color: var(--ad-Color-sec); } .ad-Choices { display: -webkit-box; display: -ms-flexbox; display: flex; width: 12rem; } .ad-Choice { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } .ad-Choice-input { display: none; } .ad-Choice-fake { padding: .6rem; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); border: 4px solid transparent; -webkit-transition: border .2s; -o-transition: border .2s; transition: border .2s; cursor: pointer; text-align: center; text-transform: uppercase; font-family: "Open Sans", sans-serif; font-size: .8rem; font-weight: bold; color: #fff; } .ad-Choice:first-child .ad-Choice-fake { border-radius: 4px 0 0 4px; } .ad-Choice:last-child .ad-Choice-fake { border-radius: 0 4px 4px 0; } .ad-Choice-input:checked + .ad-Choice-fake { border-color: #00E676; border-color: var(--ad-Color-sec); } .ad-Range { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; } .ad-Range-text { margin-left: .5rem; } .ad-Range-input { width: 100%; height: 14px; -webkit-appearance: none; -moz-appearance: none; appearance: none; border-radius: 30px; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); } .ad-Range-input:focus { outline: 0; background: color(#111 l(+20%)); background: color(var(--ad-Color-prim) l(+20%)); } /* thumb */ .ad-Range-input::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; border: 4px solid #fff; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); border-radius: 50%; cursor: pointer; -webkit-transition: border .2s; transition: border .2s; } .ad-Range-input::-moz-range-thumb { -webkit-appearance: none; width: 18px; height: 18px; border: 4px solid #fff; background: color(#111 l(+10%)); background: color(var(--ad-Color-prim) l(+10%)); border-radius: 50%; cursor: pointer; -moz-transition: border .2s; transition: border .2s; } .ad-Range-input:hover::-webkit-slider-thumb, .ad-Range-input:focus::-webkit-slider-thumb { border-color: #00E676; border-color: var(--ad-Color-sec); } .ad-Range-input:hover::-moz-range-thumb, .ad-Range-input:focus::-moz-range-thumb { border-color: #00E676; border-color: var(--ad-Color-sec); } </style> </head> <body> <!-- partial:index.partial.html --> <div id="app" class="ad-App"> </div> <!-- partial --> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/react.15.4.2.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/react-dom.15.4.2.js"></script> <script> function _extends() {_extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};return _extends.apply(this, arguments);}function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}const Component = React.Component; const render = ReactDOM.render; class Container extends Component {constructor(...args) {super(...args);_defineProperty(this, "state", { w: 800, h: 600, grid: { show: true, snap: true, size: 50 }, ctrl: false, points: [ { x: 100, y: 300 }, { x: 200, y: 300, q: { x: 150, y: 50 } }, { x: 300, y: 300, q: { x: 250, y: 550 } }, { x: 400, y: 300, q: { x: 350, y: 50 } }, { x: 500, y: 300, c: [{ x: 450, y: 550 }, { x: 450, y: 50 }] }, { x: 600, y: 300, c: [{ x: 550, y: 50 }, { x: 550, y: 550 }] }, { x: 700, y: 300, a: { rx: 50, ry: 50, rot: 0, laf: 1, sf: 1 } }], activePoint: 2, draggedPoint: false, draggedQuadratic: false, draggedCubic: false, closePath: false });_defineProperty(this, "setWidth", e => { let v = this.positiveNumber(e.target.value),min = 1; if (v < min) v = min; this.setState({ w: v }); });_defineProperty(this, "setHeight", e => { let v = this.positiveNumber(e.target.value),min = 1; if (v < min) v = min; this.setState({ h: v }); });_defineProperty(this, "setGridSize", e => { let grid = this.state.grid; let v = this.positiveNumber(e.target.value); let min = 1; let max = Math.min(this.state.w, this.state.h); if (v < min) v = min; if (v >= max) v = max / 2; grid.size = v; this.setState({ grid }); });_defineProperty(this, "setGridSnap", e => { let grid = this.state.grid; grid.snap = e.target.checked; this.setState({ grid }); });_defineProperty(this, "setGridShow", e => { let grid = this.state.grid; grid.show = e.target.checked; this.setState({ grid }); });_defineProperty(this, "setClosePath", e => { this.setState({ closePath: e.target.checked }); });_defineProperty(this, "getMouseCoords", e => { const rect = ReactDOM.findDOMNode(this.refs.svg).getBoundingClientRect(); let x = Math.round(e.pageX - rect.left); let y = Math.round(e.pageY - rect.top); if (this.state.grid.snap) { x = this.state.grid.size * Math.round(x / this.state.grid.size); y = this.state.grid.size * Math.round(y / this.state.grid.size); } return { x, y }; });_defineProperty(this, "setPointType", e => { const points = this.state.points; const active = this.state.activePoint; // not the first point if (active !== 0) { let v = e.target.value; switch (v) { case "l": points[active] = { x: points[active].x, y: points[active].y }; break; case "q": points[active] = { x: points[active].x, y: points[active].y, q: { x: (points[active].x + points[active - 1].x) / 2, y: (points[active].y + points[active - 1].y) / 2 } }; break; case "c": points[active] = { x: points[active].x, y: points[active].y, c: [ { x: (points[active].x + points[active - 1].x - 50) / 2, y: (points[active].y + points[active - 1].y) / 2 }, { x: (points[active].x + points[active - 1].x + 50) / 2, y: (points[active].y + points[active - 1].y) / 2 }] }; break; case "a": points[active] = { x: points[active].x, y: points[active].y, a: { rx: 50, ry: 50, rot: 0, laf: 1, sf: 1 } }; break;} this.setState({ points }); } });_defineProperty(this, "setPointPosition", (coord, e) => { let coords = this.state.points[this.state.activePoint]; let v = this.positiveNumber(e.target.value); if (coord === "x" && v > this.state.w) v = this.state.w; if (coord === "y" && v > this.state.h) v = this.state.h; coords[coord] = v; this.setPointCoords(coords); });_defineProperty(this, "setQuadraticPosition", (coord, e) => { let coords = this.state.points[this.state.activePoint].q; let v = this.positiveNumber(e.target.value); if (coord === "x" && v > this.state.w) v = this.state.w; if (coord === "y" && v > this.state.h) v = this.state.h; coords[coord] = v; this.setQuadraticCoords(coords); });_defineProperty(this, "setCubicPosition", (coord, anchor, e) => { let coords = this.state.points[this.state.activePoint].c[anchor]; let v = this.positiveNumber(e.target.value); if (coord === "x" && v > this.state.w) v = this.state.w; if (coord === "y" && v > this.state.h) v = this.state.h; coords[coord] = v; this.setCubicCoords(coords, anchor); });_defineProperty(this, "setPointCoords", coords => { const points = this.state.points; const active = this.state.activePoint; points[active].x = coords.x; points[active].y = coords.y; this.setState({ points }); });_defineProperty(this, "setQuadraticCoords", coords => { const points = this.state.points; const active = this.state.activePoint; points[active].q.x = coords.x; points[active].q.y = coords.y; this.setState({ points }); });_defineProperty(this, "setArcParam", (param, e) => { const points = this.state.points; const active = this.state.activePoint; let v; if (["laf", "sf"].indexOf(param) > -1) { v = e.target.checked ? 1 : 0; } else { v = this.positiveNumber(e.target.value); } points[active].a[param] = v; this.setState({ points }); });_defineProperty(this, "setCubicCoords", (coords, anchor) => { const points = this.state.points; const active = this.state.activePoint; points[active].c[anchor].x = coords.x; points[active].c[anchor].y = coords.y; this.setState({ points }); });_defineProperty(this, "setDraggedPoint", index => { if (!this.state.ctrl) { this.setState({ activePoint: index, draggedPoint: true }); } });_defineProperty(this, "setDraggedQuadratic", index => { if (!this.state.ctrl) { this.setState({ activePoint: index, draggedQuadratic: true }); } });_defineProperty(this, "setDraggedCubic", (index, anchor) => { if (!this.state.ctrl) { this.setState({ activePoint: index, draggedCubic: anchor }); } });_defineProperty(this, "cancelDragging", e => { this.setState({ draggedPoint: false, draggedQuadratic: false, draggedCubic: false }); });_defineProperty(this, "addPoint", e => { if (this.state.ctrl) { let coords = this.getMouseCoords(e); let points = this.state.points; points.push(coords); this.setState({ points, activePoint: points.length - 1 }); } });_defineProperty(this, "removeActivePoint", e => { let points = this.state.points; let active = this.state.activePoint; if (points.length > 1 && active !== 0) { points.splice(active, 1); this.setState({ points, activePoint: points.length - 1 }); } });_defineProperty(this, "handleMouseMove", e => { if (!this.state.ctrl) { if (this.state.draggedPoint) { this.setPointCoords(this.getMouseCoor.........完整代码请登录后点击上方下载按钮下载查看
网友评论0