vue-chevron
Version:
Animated chevron toggle component
187 lines (173 loc) • 4.51 kB
JavaScript
/*!
* vue-chevron v0.1.0
* (c) 2017-present Ispal <irpa.oss@gmail.com>
* Released under the MIT License.
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.VueChevron = factory());
}(this, (function () { 'use strict';
var animationId;
var lastTime = null;
function linear(t) {
return t;
}
function animate(duration, component) {
lastTime = component.progress <= 1 ? performance.now() : lastTime;
var animation = function (t) {
var progress = (t - lastTime) / duration;
if (progress >= 1) {
window.cancelAnimationFrame(animationId);
component.clickProgress = 1;
component.progress = 1;
return;
}
component.progress = component.easing(progress);
animationId = window.requestAnimationFrame(animation);
};
animationId = window.requestAnimationFrame(animation);
}
function calculatePosition(
pointDown,
progress,
lastClickProgress,
height,
viewBoxCenterY
) {
var progressWithClick =
lastClickProgress === 1 ? progress : progress + (1 - lastClickProgress);
if (progressWithClick >= 1) {
progressWithClick = 1;
}
var topY = viewBoxCenterY + height / 2 - progressWithClick * height;
var bottomY = viewBoxCenterY - height / 2 + progressWithClick * height;
return pointDown ? topY : bottomY;
}
var index = {
name: "VueChevron",
props: {
pointDown: {
type: Boolean,
default: true
},
duration: {
type: Number,
default: 500
},
thickness: {
type: Number,
default: 4
},
angle: {
type: Number,
default: 40
},
roundEdges: {
type: Boolean,
default: true
},
easing: {
type: Function,
default: linear
}
},
data: function data() {
return {
progress: 1,
clickProgress: 1,
reverse: false,
lineLength: 30
};
},
computed: {
path: function path() {
var progress = this.progress;
var ref = this.triangleSideLengths;
var width = ref.width;
var height = ref.height;
var ref$1 = this.viewBoxCenter;
var x = ref$1.x;
var y = ref$1.y;
var clickProgress = this.clickProgress;
var sidesY = calculatePosition(
this.pointDown,
progress,
clickProgress,
height,
y
);
var centerY = calculatePosition(
!this.pointDown,
progress,
clickProgress,
height,
y
);
return ("M" + (x - width) + "," + sidesY + ", " + x + "," + centerY + " " + (x + width) + "," + sidesY);
},
triangleSideLengths: function triangleSideLengths() {
var height = this.lineLength * Math.sin(this.angle * (Math.PI / 180));
var width = this.lineLength * Math.cos(this.angle * (Math.PI / 180));
return {
width: width,
height: height
};
},
viewBoxCenter: function viewBoxCenter() {
var ref = this.viewBoxSize;
var width = ref.width;
var height = ref.height;
return { x: width / 2, y: height / 2 };
},
viewBoxSize: function viewBoxSize() {
var lineLength = this.lineLength;
var thickness = this.thickness;
var width = Math.ceil(lineLength * 2 + thickness * 2);
var height = Math.ceil(
lineLength * 2 * Math.sin(this.angle * (Math.PI / 180)) + thickness * 2
);
return { width: width, height: height };
}
},
watch: {
pointDown: function() {
this.clickProgress = this.progress;
this.progress = 0;
window.cancelAnimationFrame(animationId);
animate(this.duration, this);
}
},
render: function render(h) {
var lineCapAndJoin = this.roundEdges ? "round" : "square";
var ref = this.viewBoxSize;
var width = ref.width;
var height = ref.height;
return h(
"svg",
{
attrs: {
height: 32,
width: 32,
xmlns: "http://www.w3.org/2000/svg",
viewBox: ("0 0 " + width + " " + height)
}
},
[
h("title", "vue-chevron"),
h("path", {
attrs: {
d: this.path,
fill: "none",
"stroke-linecap": lineCapAndJoin,
"stroke-width": this.thickness,
"stroke-linejoin": lineCapAndJoin,
stroke: "currentColor"
}
})
]
);
}
};
return index;
})));