桌面宠物 ② 通过js制作属于自己的web网页宠物
一、網頁寵物素材
1.1 需要準備什么素材
桌面寵物 ① 通過python制作屬于自己的桌面寵物_林林zonzon的博客-CSDN博客_python桌面寵物同前一篇文章一樣,web網頁寵物的動畫效果的實現,也是由一個個GIF圖拼接而成,我們需要準備多組GIF動圖來實現網頁寵物的動作切換。
1.2 素材的獲取方法
① 素材網站:愛給網、素材巷等。
② 通過ps、pr自己制作 :pr制作選擇視頻輸出為GIF圖即可,ps則需要一幀一幀的找靜態圖拼接到一起,具體操作流程看上篇。
③ 通過淘寶購買:【淘寶某些商家的資源挺坑的】
二、js實現代碼
2.1 目錄結構
項目的目錄結構如下,其中index.html為可以打開的網頁。
?img下的GIF圖片是網頁寵物對應的可切換動作,這里就放了4個,分別為Attack攻擊動畫、Hit受擊動畫、Idle待機動畫、Walk行走動畫。
?class下的pet.js就是網頁寵物的行為邏輯設置。
2.2 實現代碼
2.2.1 index.html中的代碼設置
<img>標簽即為展示網頁寵物的內容,設置他的class和id名都為pet,src為其讀取的資源路徑,默認讀取idle(待機)的GIF圖片
<div><img class="pet" id="pet" src="./img/Idle.gif" /> </div>?script下引入對應的JS文件
<script src="./class/pet.js" type="text/javascript"></script>?style下設置網頁寵物的展示樣式
.pet {width: 50px;height: 65px;position: absolute;background-size: cover;}2.2.2 實現功能
這次的網頁寵物實現的功能為:平常處于待機動畫狀態,在點擊寵物后,寵物播放受擊動畫,然后開始追逐鼠標,追逐到后執行攻擊動畫,攻擊動畫執行完畢后恢復待機狀態。
① 寵物元素設置
首先通過getElementById,根據id獲取對應image的相關屬性
// 獲取寵物元素 let pet = document.getElementById('pet');定義旋轉角度,寵物位置、鼠標位置、移動次數來實現寵物追逐鼠標時候位置方向的旋轉移動。
// 旋轉角度 let deg = 0; // 旋轉角度Y let deg_y = 0; // 記錄寵物位置 let position = {x: 0,y: 0, } // 記錄寵物距離鼠標需要移動的距離 let mousePosition = {x: 0,y: 0, } // 記錄當前移動次數 let count = 0; // 寵物移動到鼠標位置,所需要的次數 let speed = 50;定義相關狀態,與動畫切換時間,實現狀態切換和動畫播放
// 是否處于追逐狀態 let isCatchUp = false; // 是否處于點擊狀態 let isClick = false; // 是否處于待機狀態 let isIdle = true;// 攻擊動畫狀態記錄 let attack = {// 當前幀current: 0,// 持續時間max: 340, } // 點擊動畫狀態記錄 let click = {current: 0,max: 40 } // 行走動畫狀態記錄 let walk = {current: 0,max: 130 }② 鼠標點擊的監聽事件,將其設置為點擊狀態
// 點擊事件監聽 document.getElementById("pet").onclick = function () {isClick = true; };③ 監聽鼠標移動事件
????????首先通過當前鼠標位置-當前寵物距離瀏覽器左邊的距離-寵物寬度的中心位置的方式算出需要移動的距離mousePosition;
????????通過相關公式算出需要翻轉的角度deg;
????????判斷鼠標當時的落點與寵物離瀏覽器左邊距離的關系,根據你GIF圖的朝向調整是大于還是小于;
????????最后將count計數清零,因為每一次鼠標移動都需要重新計算鼠標距離。
// 鼠標移動事件處理 window.addEventListener('mousemove', function (event) {// 需要移動的x軸距離 = 當前鼠標位置-距離瀏覽器左邊的距離-寵物相對于瀏覽器頁面寬度/2(寬的中心位置)mousePosition.x = event.x - pet.offsetLeft - pet.clientWidth / 2;mousePosition.y = event.y - pet.offsetTop - pet.clientHeight / 2;// 需要的旋轉角度計算deg = 360 * Math.atan(mousePosition.y / mousePosition.x) / (2 * Math.PI);// 這里的event.clientX 返回當事件被觸發時鼠標指針相對于瀏覽器頁面(或客戶區)的水平坐標。// 這里有關于圖片位置的設置,注意你的gif圖的方向,原圖方向向左,那么這里就是小于,原圖方向向右,這里就是大于。// 翻轉圖片if (pet.offsetLeft > event.clientX) {deg_y = - 180;} else {deg_y = 0;}//這里每一次移動鼠標都要重新計算距離,所以這里的count需要清零count = 0; })④ 寵物更新狀態事件,網頁寵物的動作切換流程,主體由setInterval完成,setInterval為一個不斷執行的定時函數,每過10毫秒循環執行。
// 每過10毫秒,循環執行 setInterval(() => {// 處于追逐鼠標狀態if (isCatchUp == false && isIdle == false) {catchUpState();}// 處于攻擊狀態else if (isCatchUp == true && isIdle == false) {attackState();}// 處于點擊狀態else if (isClick == true) {clickState();} }, 10)⑤ 鼠標追逐狀態 catchUpState()
用walk.current模擬GIF播放的當前幀,walk.max模擬GIF圖的一次播放時間。 ?walk.current = 1 就相當于GIF播放到第1幀。
function catchUpState() {// 準備播放追逐狀態動畫if (walk.current == 0) {(1)......}// 開始播放追逐狀態GIFelse if (walk.current < walk.max) {(2)......}// 結束播放追逐狀態GIF,同時開始重新播放追逐狀態GIF圖else if (walk.current >= walk.max) {(3)......}}?(1)在current等于0時,切換成需要的GIF圖,并根據你自己GIF圖的大小決定調整情況,最后current++。
// 此時寵物為追逐狀態,gif圖切換為walk.gifdocument.getElementById("pet").src = "./img/Walk.gif" // 因為不同的GIF圖對應的寬高可能有差別,需要調整的可以在這里調整pet.style.width = 50 + "px" // 當前動畫幀+1walk.current++(2)在current>0而小于設定的max時 ,就執行當前狀態下的一些操作。
walk狀態下,首先根據我們在鼠標監聽事件中獲取的deg調整寵物旋轉角度。
// 調整寵物角度 pet.style.transform = "rotateZ(" + deg + "deg) rotateY(" + deg_y + "deg)"然后再通過count和speed的大小判斷寵物是否到達鼠標位置,沒到達就改變寵物對應的位置,到達就調整寵物狀態。【speed為我們設定的需要移動距離的份數,count為當前移動距離的份數】
// 如果沒追到鼠標 if (count < speed) {// position.x和y分別記錄當前寵物的橫縱坐標位置// 此時的橫縱坐標位置,通過+=的方式移過去,speed越大,移動速度越慢// 相當于將兩點之間的位置分為speed份,每一次刷新移動一份的距離position.x += mousePosition.x / speedposition.y += mousePosition.y / speed } // 追到鼠標 else {// 改變狀態isCatchUp = true }?最后改變寵物實際的樣式屬性,實現寵物的移動。
// 實際的畫出當前的寵物位置pet.style.left = position.x + "px"pet.style.top = position.y + "px"count++walk.current++;(3)在current>=max時,即是行走動畫播放完畢,在walk狀態下,如果沒有追逐到鼠標,將會繼續循環播放walk.gif動畫。
//當前幀歸零walk.current = 0;//繼續播放walk.gif圖片document.getElementById("pet").src = "./img/Walk.gif"⑥ 寵物攻擊狀態 attackState(),這里的邏輯和上面的邏輯是一樣的,就不過多講述了。
function attackState() {// 準備播放攻擊狀態動畫if (attack.current == 0) {// 調整播放的動畫document.getElementById("pet").src = "./img/Attack.gif"pet.style.width = 100 + "px"attack.current++}// 開始播放攻擊狀態動畫,這里可以拓展在某些幀(current計數)的時候設置攻擊范圍和攻擊處理函數之類的else if (attack.current < attack.max) {attack.current++;}// 結束播放攻擊動畫,改變對應狀態,播放待機動畫。else if (attack.current >= attack.max) {// 將動畫設置復原isCatchUp = false;isIdle = true;attack.current = 0;document.getElementById("pet").src = "./img/Idle.gif"pet.style.width = 50 + "px"}}?⑦ 寵物點擊狀態 clickState()
function clickState() {// 準備播放受擊動畫if (click.current == 0) {document.getElementById("pet").src = "./img/Hit.gif"pet.style.width = 60 + "px"click.current++}// 開始播放受擊動畫,可以在這里面處理對應受擊動作函數else if (click.current < click.max) {click.current++;}// 結束播放受擊動畫,改變狀態,播放行走動畫else if (click.current >= click.max) {click.current = 0;document.getElementById("pet").src = "./img/Walk.gif"pet.style.width = 50 + "px"isClick = false;isIdle = false;}}2.3 完整源碼
2.3.1 index.html
<!DOCTYPE html> <html lang="en"> <body><div><img class="pet" id="pet" src="./img/Idle.gif" /></div> </body><script src="./class/pet.js" type="text/javascript"></script> <style>.pet {width: 50px;height: 65px;position: absolute;background-size: cover;} </style> </html>2.3.2 pet.js
// 獲取寵物元素 let pet = document.getElementById('pet'); // 旋轉角度 let deg = 0; // 旋轉角度Y let deg_y = 0; // 記錄寵物距離鼠標需要移動的距離 let mousePosition = {x: 0,y: 0, } // 記錄寵物位置 let position = {x: 0,y: 0, }// 記錄當前移動次數 let count = 0; // 寵物移動到鼠標位置,所需要的次數 let speed = 50;// 是否處于追逐狀態 let isCatchUp = false; // 是否處于點擊狀態 let isClick = false;// 是否處于待機狀態 let isIdle = true;// 攻擊動畫狀態記錄 let attack = {// 當前幀current: 0,// 持續時間max: 340, } // 點擊動畫狀態記錄 let click = {current: 0,max: 40 }// 行走動畫狀態記錄 let walk = {current: 0,max: 130 }// 點擊事件處理 document.getElementById("pet").onclick = function () {isClick = true; };// 鼠標移動事件處理 window.addEventListener('mousemove', function (event) {// 期望圖片移動到的鼠標x軸位置 = 當前鼠標位置-距離瀏覽器左邊的距離-寵物相對于瀏覽器頁面寬度/2(寬的中心位置)mousePosition.x = event.x - pet.offsetLeft - pet.clientWidth / 2;mousePosition.y = event.y - pet.offsetTop - pet.clientHeight / 2;// 旋轉角度deg = 360 * Math.atan(mousePosition.y / mousePosition.x) / (2 * Math.PI);// clientX 事件屬性返回當事件被觸發時鼠標指針相對于瀏覽器頁面(或客戶區)的水平坐標。// 這里有關于圖片位置的設置,注意你的gif圖的方向,原圖方向向左,那么這里就是小于,原圖方向向右,這里就是大于。// 翻轉圖片if (pet.offsetLeft > event.clientX) {deg_y = - 180;} else {deg_y = 0;}//這里每一次移動鼠標都要重新計算距離,所以這里的count需要清零count = 0; })// 每過10毫秒,循環執行 setInterval(() => {// 處于追逐鼠標狀態if (isCatchUp == false && isIdle == false) {catchUpState();}// 處于攻擊狀態else if (isCatchUp == true && isIdle == false) {attackState();}// 處于點擊狀態else if (isClick == true) {clickState();} }, 10)function catchUpState() {// 準備播放追逐狀態動畫if (walk.current == 0) {// 此時寵物為追逐狀態,gif圖切換為walk.gifdocument.getElementById("pet").src = "./img/Walk.gif"// 因為不同的GIF圖對應的寬高可能有差別,需要調整的可以在這里調整pet.style.width = 50 + "px"// 當前動畫幀+1walk.current++}// 開始播放追逐狀態GIFelse if (walk.current < walk.max) {// 調整寵物角度pet.style.transform = "rotateZ(" + deg + "deg) rotateY(" + deg_y + "deg)"// 如果沒追到鼠標if (count < speed) {// position.x和y分別記錄當前寵物的橫縱坐標位置// 此時的橫縱坐標位置,通過+=的方式移過去,speed越大,移動速度越慢// 相當于將兩點之間的位置分為speed份,每一次刷新移動一份的距離position.x += mousePosition.x / speedposition.y += mousePosition.y / speed}// 追到鼠標else {// 改變狀態isCatchUp = truewalk.current = 0}// 實際的畫出當前的寵物位置pet.style.left = position.x + "px"pet.style.top = position.y + "px"count++walk.current++;}// 結束播放追逐狀態GIF,同時開始重新播放追逐狀態GIF圖else if (walk.current >= walk.max) {walk.current = 0;document.getElementById("pet").src = "./img/Walk.gif"}}function attackState() {// 準備播放攻擊狀態動畫if (attack.current == 0) {// 調整播放的動畫document.getElementById("pet").src = "./img/Attack.gif"pet.style.width = 100 + "px"attack.current++}// 開始播放攻擊狀態動畫,這里可以拓展在某些幀(current計數)的時候設置攻擊范圍和攻擊處理函數之類的else if (attack.current < attack.max) {attack.current++;}// 結束播放攻擊動畫,改變對應狀態,播放待機動畫。else if (attack.current >= attack.max) {// 將動畫設置復原isCatchUp = false;isIdle = true;attack.current = 0;document.getElementById("pet").src = "./img/Idle.gif"pet.style.width = 50 + "px"}}function clickState() {// 準備播放受擊動畫if (click.current == 0) {document.getElementById("pet").src = "./img/Hit.gif"pet.style.width = 60 + "px"click.current++}// 開始播放受擊動畫,可以在這里面處理對應受擊動作函數else if (click.current < click.max) {click.current++;}// 結束播放受擊動畫,改變狀態,播放行走動畫else if (click.current >= click.max) {click.current = 0;document.getElementById("pet").src = "./img/Walk.gif"pet.style.width = 50 + "px"isClick = false;isIdle = false;}}三、在vue項目中展示網頁寵物
做這個東西主要還是想把他放在自己的個人網站上面,讓網站內容不至于過于空虛。放在vue上面的話,大體沒啥問題,主要是注意放的位置就歐克了,建議放在絕對路徑里面。
3.1 資源位置
這里資源放置的路徑,建議將寵物的GIF圖片放在項目public下面的文件夾中,不然可能無法正常加載。
?.js文件和.vue文件同正常一樣即可。
3.2 pet.js代碼
將整個js代碼用一個函數start包起來,然后每個涉及到圖片地址的用public下的絕對路徑代替即可。
export function start() {let pet = document.getElementById('pet');......function catchUpState() {if (walk.current == 0) {// document.getElementById("pet").src = "./img/Walk.gif"document.getElementById("pet").src = "/image/pet/Walk.gif"......}......}3.3 vue界面代碼
引入pet.js里面的start方法,這個需要在mounted里面初始化,不能放在created()里面進行初始化,不然會報錯。
<template><div><img class="pet" id="pet" src="/image/pet/Idle.gif" /></div> </template><script> import { start } from "../util/pet.js"; export default {// 某些父子組件交互的值data() {return {};},mounted() {start();},methods: {}, }; </script><style scoped lang="less"> .pet {width: 50px;height: 65px;position: absolute;background-size: cover; } </style>四、總結
4.1 項目百度網盤
百度網盤鏈接: https://pan.baidu.com/s/1585QjxSWWdX2eOXXECGpVg
提取碼: hia9
vue為vue項目上更改過的文件
webpet則是可以直接打開index.html的文件
4.2 總結
還有很多等待優化的地方,只是一個小小的demo,做著玩的,不過收獲的確很多。可能有些地方會出現問題,有問題私信或者評論區留言,咱們共同探討🐵
總結
以上是生活随笔為你收集整理的桌面宠物 ② 通过js制作属于自己的web网页宠物的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 巴菲特致股东的一封信:2012年 和学习
- 下一篇: 02、cordic算法原理及verilo