效果圖:
拖拽.gif
參考效果地址:http://www.jq22.com/yanshi4688
image.png
此篇文章是我根據(jù)效果,自己仿寫的效果逐哈,并沒有直接使用以上地址的代碼~~(主要是下了也看不懂??)
這里大致告訴大家怎么實(shí)現(xiàn)這種效果的,其他相關(guān)內(nèi)容小伙伴們可以根據(jù)需要,自行擴(kuò)展??
標(biāo)題已經(jīng)說的很明白了缓苛,用的 vue+svg+animejs,svg圖片需要自己繪制,不太會animejs的可以自行百度邓深,去看人家的官方文檔未桥。
需要繪制的圖片為4張:
//1.初始狀態(tài)
d="m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
//2.拉伸時狀態(tài)
d="m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c132.71929,-76.58717 132.2807,-323.17434 0.26316,-398.70888z"
//3.最終狀態(tài)
d= "m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c0.24214,-132.90296 0.48428,-265.80592 0.72642,-398.70888z"
//4.恢復(fù)到初始時的狀態(tài)
d="m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c-90.81049,-132.37664 -97.93677,-266.85855 0.72642,-398.70888z"
image.png
整體連貫起來就是這樣的:
拖拽1.gif
??簡單的animejs,就能實(shí)現(xiàn)這種動畫變換過程
anime({
targets: "#svg_1",
d: [
{
value:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
},
{
value:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c132.71929,-76.58717 132.2807,-323.17434 0.26316,-398.70888z"
},
{
value:
"m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c0.24214,-132.90296 0.48428,-265.80592 0.72642,-398.70888z"
},
{
value:
"m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c-90.81049,-132.37664 -97.93677,-266.85855 0.72642,-398.70888z"
},
{
value:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
}
],
duration: 5000,
loop: 1
});
??這個原理大致了解之后,接下來就是在哪個過程中調(diào)用哪個階段就可以了芥备,詳細(xì)的代碼上都有注釋的冬耿,想要記得更加深刻的最好自己動手操作~~~??
代碼如下:
<template>
<div class="overall" @click="close_path" @mousedown="m_d_path" @mouseup="m_u_path">
<div class="box">
<svg viewBox="0 0 300 400">
<path
@mousemove="m_m_path"
id="svg_1"
d="m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
/>
</svg>
<div class="chat_box" @click.prevent="path_open == true">
<div class="chat_msg" v-for="(m,index) in 20" :key="index">
<span>Massage_{{index+1}}</span>
<span class="dot"></span>
</div>
</div>
</div>
</div>
</template>
<script>
import anime from "animejs/lib/anime.es.js";
export default {
watch: {
path_open(newVal, oldVal) {
if (!newVal) {
anime({
targets: "#svg_1",
d: [
{
value:
"m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c-90.81049,-132.37664 -97.93677,-266.85855 0.72642,-398.70888z",
duration: 100,
easing: "easeInQuad"
},
{
value:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z",
duration: 300
}
],
begin: function() {
anime({
targets: ".chat_box",
translateX: [0, -160],
opacity: 0,
duration: 0
});
}
});
}
}
},
data() {
return {
box_el: null, //容器標(biāo)簽
path_el: null, //獲取 path 標(biāo)簽
down_m_x: 0, //鼠標(biāo)點(diǎn)擊時的坐標(biāo)
click_on: false, //是否處于拖拉狀態(tài)
path_open: false, //左側(cè)拉伸框是否打開
stretch: 0, //拉伸長度
pathList: [
//默認(rèn)狀態(tài)
{
value:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
},
//拉伸時狀態(tài)
{
value:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c132.71929,-76.58717 132.2807,-323.17434 0.26316,-398.70888z"
},
//最終狀態(tài)
{
value:
"m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c0.24214,-132.90296 0.48428,-265.80592 0.72642,-398.70888z"
},
//回收時狀態(tài)
{
value:
"m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c-90.81049,-132.37664 -97.93677,-266.85855 0.72642,-398.70888z"
}
]
};
},
mounted() {
let _this = this;
_this.path_el = document.querySelector("#svg_1");
_this.box_el = document.querySelector(".box");
// anime({
// targets: "#svg_1",
// d: [
// {
// value:
// "m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
// },
// {
// value:
// "m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c132.71929,-76.58717 132.2807,-323.17434 0.26316,-398.70888z"
// },
// {
// value:
// "m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c0.24214,-132.90296 0.48428,-265.80592 0.72642,-398.70888z"
// },
// {
// value:
// "m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c-90.81049,-132.37664 -97.93677,-266.85855 0.72642,-398.70888z"
// },
// {
// value:
// "m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
// }
// ],
// duration: 5000,
// loop: true
// });
},
methods: {
//鼠標(biāo)點(diǎn)擊
m_d_path(e) {
console.log("鼠標(biāo)點(diǎn)擊");
this.click_on = true;
this.down_m_x = e.clientX;
},
//鼠標(biāo)點(diǎn)擊后 + 移動(拖拽時)
m_m_path(e) {
//拉伸的距離長度
// e.clientX 鼠標(biāo)當(dāng)前最新的坐標(biāo)位置
// this.down_m_x 鼠標(biāo)最初的點(diǎn)擊坐標(biāo)位置
//當(dāng)左側(cè)拉伸框是打開狀態(tài)下,不再執(zhí)行以下操作
let left = this.box_el.offsetLeft;
// this.down_m_x > left 防止用戶直接從左側(cè)拉伸進(jìn)入容器時萌壳,左側(cè)框直接被拉開
if (!this.path_open && this.down_m_x > left) {
this.stretch = e.clientX - this.down_m_x; //拉伸長度
if (this.stretch > 0 && this.click_on) {
console.log(this.stretch);
this.path_el.setAttribute(
"d",
`m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c${this.stretch},-132.90296 ${this.stretch},-265.80592 0.26316,-398.70888z`
);
}
} else {
// alert("我已經(jīng)被拉開了");
}
},
//鼠標(biāo)松開
m_u_path(e) {
console.log("鼠標(biāo)松開");
let left = this.box_el.offsetLeft;
//當(dāng)左側(cè)拉伸框是打開狀態(tài)下亦镶,不再執(zhí)行以下操作
// this.down_m_x > left 防止用戶直接從左側(cè)拉伸進(jìn)入容器時,左側(cè)框直接被拉開
//this.stretch > 0 防止關(guān)閉左側(cè)拉伸框時袱瓮,用戶重復(fù)點(diǎn)擊問題
if (!this.path_open && this.down_m_x > left && this.stretch > 0) {
//如果拖拉距離超過50缤骨,則展開
if (this.stretch > 50) {
let _this = this;
anime({
targets: "#svg_1",
duration: 300,
d:
"m158.1579,0.7648l-157.63158,-0.23848l0,398.94736l156.90516,0c0.24214,-132.90296 0.48428,-265.80592 0.72642,-398.70888z",
complete: function(anim) {
//動畫完成后,會觸發(fā)一次complete()回調(diào)尺借。
_this.path_open = true;
anime({
targets: ".chat_box",
translateX: [-160, 0],
opacity: 1,
duration: 0
});
}
});
} else {
//不超過50 則恢復(fù)
anime({
targets: "#svg_1",
duration: 200,
d:
"m57.63158,0.7648l-57.10526,-0.23848l0,398.94736l56.8421,0c0.08772,-132.90296 0.17544,-265.80592 0.26316,-398.70888z"
});
}
} else {
// alert("我已經(jīng)被拉開了");
}
this.click_on = false;
},
//關(guān)閉左側(cè)拉伸框
close_path(e) {
console.log(e.target);
// 主要運(yùn)用了事件的冒泡
//判斷點(diǎn)擊除 左側(cè)拉伸框 外其他部分绊起,全部為關(guān)閉 左側(cè)拉伸框
if (
e.target == this.box_el ||
e.target == document.querySelector(".overall")
) {
//關(guān)閉后重置 左側(cè)拉伸框狀態(tài) 拉伸長度
this.path_open = false;
this.stretch = 0;
} else {
return;
}
}
}
};
</script>
<style lang="scss" scoped>
.overall {
background: #65698f;
}
svg {
width: 100%;
height: 100%;
transform: scale(1.05);
}
path {
cursor: grab;
fill: rgba(255, 255, 255, 0.966);
stroke-width: 0;
stroke-linecap: round;
stroke-linejoin: round;
}
.box {
width: 300px;
height: 400px;
background: #6d7ada;
overflow: hidden;
position: relative;
.chat_box {
width: 160px;
height: 100%;
// background: red;
position: absolute;
left: 0;
top: 0;
z-index: 9;
overflow-y: scroll;
opacity: 0;
transform: translateX(-160px);
&::-webkit-scrollbar {
opacity: 0;
background: rgba(204, 204, 204, 0.685) !important;
width: 2px; //y軸滾輪的寬
// height: 2px; //x軸滾輪的高
}
&::-webkit-scrollbar-thumb {
/*滾動條里面小方塊*/
border-radius: 10px;
-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background: white;
}
&::-webkit-scrollbar-track {
/*滾動條里面軌道*/
// -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
// border-radius: 10px;
background: transparent;
// -webkit-scrollBar-track-color:black;
}
.chat_msg {
margin: 0 5px;
height: 60px;
border-bottom: 1px solid #f0f0f0;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
color: #5a5a5a;
font-weight: bold;
position: relative;
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: rgb(25, 238, 185);
position: absolute;
right: 5%;
}
}
}
}
</style>