<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tween.js@16.3.4"></script>
<script src="https://cdn.jsdelivr.net/npm/color-js@1.0.3"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenLite.min.js"></script>
</head>
<body>
<div>
<h1>--狀態(tài)動(dòng)畫與偵聽器1--</h1>
<div id="example1">
<input v-model.number="number" type="number" step="20">
<p>{{ animatedNumber }}</p>
</div>
<script>
var example1 = new Vue({
el: '#example1',
data: {
number: 0,
tweenedNumber: 0
},
computed: {
animatedNumber: function() {
return this.tweenedNumber.toFixed(0);
}
},
watch: {
number: function(newValue) {
TweenLite.to(this.$data, 0.5, { tweenedNumber: newValue });
}
}
})
</script>
</div>
<div>
<h1>--狀態(tài)動(dòng)畫與偵聽器2--</h1>
<div id="example2">
<input
v-model="colorQuery"
v-on:keyup.enter="updateColor"
placeholder="Enter a color"
>
<button v-on:click="updateColor">Update</button>
<p>Preview:</p>
<span
v-bind:style="{ backgroundColor: tweenedCSSColor }"
class="example-7-color-preview"
></span>
<p>{{ tweenedCSSColor }}</p>
</div>
<script>
var Color = net.brehaut.Color
var example2 = new Vue({
el: '#example2',
data: {
colorQuery: '',
color: {
red: 0,
green: 0,
blue: 0,
alpha: 1
},
tweenedColor: {}
},
created: function () {
this.tweenedColor = Object.assign({}, this.color)
},
watch: {
color: function () {
function animate () {
if (TWEEN.update()) {
requestAnimationFrame(animate)
}
}
new TWEEN.Tween(this.tweenedColor)
.to(this.color, 750)
.start()
animate()
}
},
computed: {
tweenedCSSColor: function () {
return new Color({
red: this.tweenedColor.red,
green: this.tweenedColor.green,
blue: this.tweenedColor.blue,
alpha: this.tweenedColor.alpha
}).toCSS()
}
},
methods: {
updateColor: function () {
this.color = new Color(this.colorQuery).toRGB()
this.colorQuery = ''
}
}
})
</script>
<style>
.example-7-color-preview {
display: inline-block;
width: 50px;
height: 50px;
}
</style>
</div>
<div>
<h1>--動(dòng)態(tài)狀態(tài)過渡--</h1>
<div id="svg-polygon-demo" class="demo">
<svg width="200" height="200" class="demo-svg">
<polygon :points="points" class="demo-polygon"/>
<circle cx="100" cy="100" r="90" class="demo-circle"/>
</svg>
<label>Sides: {{ sides }}</label>
<input class="demo-range-input" type="range" min="3" max="500" v-model.number="sides">
<label>Minimum Radius: {{ minRadius }}%</label>
<input class="demo-range-input" type="range" min="0" max="90" v-model.number="minRadius">
<label>Update Interval: {{ updateInterval }} milliseconds</label>
<input class="demo-range-input" type="range" min="10" max="2000" v-model.number="updateInterval">
</div>
<script>
new Vue({
el: '#svg-polygon-demo',
data: function () {
var defaultSides = 10
var stats = Array.apply(null, { length: defaultSides })
.map(function () { return 100 })
return {
stats: stats,
points: generatePoints(stats),
sides: defaultSides,
minRadius: 50,
interval: null,
updateInterval: 500
}
},
watch: {
sides: function (newSides, oldSides) {
var sidesDifference = newSides - oldSides
if (sidesDifference > 0) {
for (var i = 1; i <= sidesDifference; i++) {
this.stats.push(this.newRandomValue())
}
} else {
var absoluteSidesDifference = Math.abs(sidesDifference)
for (var i = 1; i <= absoluteSidesDifference; i++) {
this.stats.shift()
}
}
},
stats: function (newStats) {
TweenLite.to(
this.$data,
this.updateInterval / 1000,
{ points: generatePoints(newStats) }
)
},
updateInterval: function () {
this.resetInterval()
}
},
mounted: function () {
this.resetInterval()
},
methods: {
randomizeStats: function () {
var vm = this
this.stats = this.stats.map(function () {
return vm.newRandomValue()
})
},
newRandomValue: function () {
return Math.ceil(this.minRadius + Math.random() * (100 - this.minRadius))
},
resetInterval: function () {
var vm = this
clearInterval(this.interval)
this.randomizeStats()
this.interval = setInterval(function () {
vm.randomizeStats()
}, this.updateInterval)
}
}
})
function valueToPoint (value, index, total) {
var x = 0
var y = -value * 0.9
var angle = Math.PI * 2 / total * index
var cos = Math.cos(angle)
var sin = Math.sin(angle)
var tx = x * cos - y * sin + 100
var ty = x * sin + y * cos + 100
return { x: tx, y: ty }
}
function generatePoints (stats) {
var total = stats.length
return stats.map(function (stat, index) {
var point = valueToPoint(stat, index, total)
return point.x + ',' + point.y
}).join(' ')
}
</script>
<style>
.demo-svg { display: block; }
.demo-polygon { fill: #41B883; }
.demo-circle {
fill: transparent;
stroke: #35495E;
}
.demo-range-input {
display: block;
width: 100%;
margin-bottom: 15px;
}
</style>
</div>
<div>
<h1>把過渡放到組件里</h1>
<div id="example-8">
<input v-model.number="firstNumber" type="number" step="20"> +
<input v-model.number="secondNumber" type="number" step="20"> =
{{ result }}
<p>
<animated-integer v-bind:value="firstNumber"></animated-integer> +
<animated-integer v-bind:value="secondNumber"></animated-integer> =
<animated-integer v-bind:value="result"></animated-integer>
</p>
</div>
<script>
Vue.component('animated-integer', {
template: '<span>{{ tweeningValue }}</span>',
props: {
value: {
type: Number,
required: true
}
},
data: function () {
return {
tweeningValue: 0
}
},
watch: {
value: function (newValue, oldValue) {
this.tween(oldValue, newValue)
}
},
mounted: function () {
this.tween(0, this.value)
},
methods: {
tween: function (startValue, endValue) {
var vm = this
function animate () {
if (TWEEN.update()) {
requestAnimationFrame(animate)
}
}
new TWEEN.Tween({ tweeningValue: startValue })
.to({ tweeningValue: endValue }, 500)
.onUpdate(function () {
vm.tweeningValue = this.tweeningValue.toFixed(0)
})
.start()
animate()
}
}
})
new Vue({
el: '#example-8',
data: {
firstNumber: 20,
secondNumber: 40
},
computed: {
result: function () {
return this.firstNumber + this.secondNumber
}
}
})
</script>
</div>
</body>
</html>