vue delaunay实现狗脸变成猫脸变形动画效果代码
代码语言:html
所属分类:动画
代码描述:vue delaunay实现狗脸变成猫脸变形动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body { margin: 0; font-family: Georgia, sans-serif; background: orange; } body h1 { margin: 0; padding: 1em 0; text-align: center; background: steelblue; color: lightcyan; text-shadow: 0.2em 0.2em 0 rgba(0, 0, 0, 0.2); } body button { padding: 1em; font: inherit; } body footer { padding: 2em 1em; background: orangered; color: lightgoldenrodyellow; } body footer a { color: gold; } #app { text-align: center; padding: .5em 0; background: aliceblue; } #app .group { display: inline-block; vertical-align: top; margin: .5em .8em; } #app .group button { display: block; margin: auto; margin-bottom: .5em; } #app .image-container { position: relative; display: inline-block; background: white; } #app .image-container .draw-area { text-align: left; overflow: hidden; } #app .image-container input { position: absolute; z-index: -1; opacity: 0; width: 0; } #app .image-container input + span { position: relative; display: block; padding: .5em; box-sizing: border-box; background: purple; color: white; cursor: pointer; } #app .image-container input:focus + span, #app .image-container input:active + span, #app .image-container input + span:hover { background: darkviolet; outline: 2px solid violet; } #app #morph { position: relative; display: table; } #app #morph canvas { background: white; } #app #morph canvas + canvas { position: absolute; top: 0; left: 0; } #app .image-container, #app #morph { box-shadow: 0 0 0 1px paleturquoise; } #app svg { position: absolute; top: 0; left: 0; } #app svg .connector { stroke: rgba(30, 144, 255, 0.5); stroke-width: 1; stroke-dasharray: 2; pointer-events: none; } #app svg [data-draggable] { stroke: black; fill: rgba(255, 255, 255, 0.2); fill: url(#point-grad); cursor: move; } #app svg [data-draggable].selected { fill: rgba(255, 255, 0, 0.5); } #app pre { -webkit-box-flex: 1; flex: 1 1 auto; margin: .5em 1em; background: white; color: #888; border: 1px solid gainsboro; overflow: auto; } </style> </head> <body> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue@2.6.1.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/delaunay-fast.1.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/abo-utils.0.3.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/drag-tracker.1.js"></script> <h1>HyperMorph 3000™</h1> <svg width="0" height="0" style="position:absolute;"> <defs> <radialGradient id="point-grad"> <stop offset="80%" stop-color="transparent"/> <stop offset="81%" stop-color="white"/> </radialGradient> </defs> </svg> <section id="app"> <div id="prepare" class="group"> <button @click="clear">Clear</button> <div id="image1" class="image-container"> <div class="draw-area" :style="sizer()"> <canvas class="img"></canvas> <triangulator :model="state.tri1" :selected-index="state.selectedIndex" @added="onAdded" @selected="onSelected" @deleted="onDeleted"></triangulator> </div> <label> <input type="file" accept="image/*"> <span>Change image</span> </label> </div> <div id="image2" class="image-container"> <div class="draw-area" :style="sizer()"> <canvas class="img"></canvas> <triangulator :model="state.tri2" :selected-index="state.selectedIndex" @added="onAdded" @selected="onSelected" @deleted="onDeleted"></triangulator> </div> <label> <input type="file" accept="image/*"> <span>Change image</span> </label> </div> </div> <div id="apply" class="group"> <button @click="warp">Morph</button> <div id="morph"> <canvas id="c1" :width="state.size.w" :height="state.size.h"></canvas> <canvas id="c2" :width="state.size.w" :height="state.size.h"></canvas> </div> </div> <!----> <pre>{{ state | prettyCompact }}</pre> </section> <!-- SVG UI --> <script> Vue.component('drag-node', { template: '<circle data-draggable @dragging="onDragging" :cx="absCoord[0]" :cy="absCoord[1]" :r="r" />', props: { r: { default: 16 }, coord: Array, //If 'coord' is relative to some other point: offsetCenter: Array, }, model: { prop: 'coord', event: 'do_it', }, computed: { absCoord() { const point = this.coord, center = this.offsetCenter, absCoord = center ? [ point[0] + center[0], point[1] + center[1] ] : point; return absCoord; }, }, methods: { onDragging(e) { const point = e.detail.pos, center = this.offsetCenter, relCoord = center ? [ point[0] - center[0], point[1] - center[1] ] : point; this.$emit('do_it', relCoord); }, }, }); Vue.component('connector', { template: '<line class="connector" :x1="start[0]" :y1="start[1]" :x2="absEnd[0]" :y2="absEnd[1]" />', props: ['start', 'end', 'endIsRel'], computed: { absEnd() { const start = this.start, end = this.end, absEnd = this.endIsRel ? [ start[0] + end[0], start[1] + end[1] ] : end; return absEnd; } } }); </script> <script> /** * Uses Delaunay triangulation to divide a rectangle into triangles. */ class Triangulator { constructor(size, points) { this.size = size; this.points = points || []; } getEffectivePoints(.........完整代码请登录后点击上方下载按钮下载查看
网友评论0