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