点赞效果修改

master
于肖磊 2025-12-02 11:02:28 +08:00
parent 4317698dc3
commit addde47054
5 changed files with 113 additions and 90 deletions

View File

@ -1,43 +1,45 @@
<template>
<view class="simple-like-container">
<!-- 点赞动画元素 -->
<view
v-for="(like, index) in likeList"
:key="like.id"
class="like-item"
:ref="'likeItem' + like.id"
:style="{
left: like.x + 'px',
top: like.y + 'px',
color: like.color,
opacity: like.opacity
}"
>
<!-- 支持图片或自定义图标 -->
<image
v-if="like.imageSrc"
:src="like.imageSrc"
class="like-image"
mode="aspectFit"
></image>
<text v-else>{{ like.icon }}</text>
</view>
<!-- 连续点赞数量提示 -->
<view
v-if="showLikeCount && likeCount >= 3"
class="like-count"
:ref="'likeCount'"
:style="{
left: likeCountPosition.x + 'px',
top: likeCountPosition.y + 'px',
color: likeCountColor,
opacity: likeCountOpacity,
transform: 'scale(' + likeCountScale + ')'
}"
>
x {{ likeCount }}
</view>
<view class="simple-like-container flex-row box-border-box">
<view class="flex-1 pr">
<!-- 点赞动画元素 -->
<view
v-for="(like, index) in likeList"
:key="like.id"
class="like-item"
:ref="'likeItem' + like.id"
:style="{
left: like.x + 'px',
top: like.y + 'px',
color: like.color,
opacity: like.opacity
}"
>
<!-- 支持图片或自定义图标 -->
<image
v-if="like.imageSrc"
:src="like.imageSrc"
class="like-image"
mode="aspectFit"
></image>
<text v-else>{{ like.icon }}</text>
</view>
<!-- 连续点赞数量提示 -->
<text
v-if="showLikeCount && likeCount >= 3"
class="like-count"
:ref="'likeCount'"
:style="{
left: likeCountPosition.x + 'px',
top: likeCountPosition.y + 'px',
color: likeCountColor,
opacity: likeCountOpacity,
transform: 'scale(' + likeCountScale + ')'
}"
>
x {{ likeCount }}
</text>
</view>
</view>
</template>
@ -75,7 +77,8 @@
likeCountScale: 1,
lastLikeTime: 0,
likeCountTimer: null,
resetTimer: null //
resetTimer: null, //
lastClickTime: 0 //
}
},
computed: {
@ -90,6 +93,13 @@
},
methods: {
addLike(event, options = {}) {
//
const now = Date.now();
if (now - this.lastClickTime < 200) {
return;
}
this.lastClickTime = now;
//
let x, y;
//
@ -106,13 +116,13 @@
console.log('Click coordinates:', x, y);
// (-20px 20px)
const offsetX = Math.floor(Math.random() * 41) - 20;
const offsetY = Math.floor(Math.random() * 41) - 20;
// (-10px 10px)
const offsetX = Math.floor(Math.random() * 41) - 10;
const offsetY = Math.floor(Math.random() * 41) - 10;
// 20px
const clampedOffsetX = Math.max(-20, Math.min(20, offsetX));
const clampedOffsetY = Math.max(-20, Math.min(20, offsetY));
const clampedOffsetX = Math.max(-10, Math.min(10, offsetX));
const clampedOffsetY = Math.max(-10, Math.min(10, offsetY));
//
const adjustedX = x + clampedOffsetX - 10;
@ -157,7 +167,7 @@
icon: icon,
imageSrc: imageSrc
};
console.log(newLike, '111');
//
this.likeList.push(newLike);
console.log('Added like item:', newLike);
@ -186,6 +196,12 @@
this.resetTimer = null;
}
//
if (this.likeCountTimer) {
clearTimeout(this.likeCountTimer);
this.likeCountTimer = null;
}
// 1
if (currentTime - this.lastLikeTime > 1000) {
this.likeCount = 1;
@ -217,22 +233,18 @@
});
}
//
if (this.likeCountTimer) {
clearTimeout(this.likeCountTimer);
}
// 1000ms
// 200ms
if (this.likeCount >= 3) {
this.likeCountTimer = setTimeout(() => {
this.hideLikeCount();
// 1
this.resetTimer = setTimeout(() => {
this.likeCount = 0;
}, 1000);
}, 1000); // 200ms
}, 200);
}
// 1
this.resetTimer = setTimeout(() => {
this.likeCount = 0;
this.showLikeCount = false;
}, 1200);
},
//
@ -343,9 +355,11 @@
position: absolute;
top: 0;
left: 0;
/* #ifndef-nvue */
width: 100%;
height: 100%;
pointer-events: none;
/* #endif */
z-index: 9999;
}
@ -374,7 +388,7 @@
.like-count {
opacity: 1;
animation: shrinkUp 0.2s ease-out forwards;
animation: shrinkUp 1s ease-out forwards;
}
@keyframes zoomInOut {

View File

@ -7,14 +7,14 @@
<!-- #endif -->
<!-- 顶部主播信息 -->
<view class="flex-row align-c jc-sb" :style="header_style">
<view class="top-header flex-row align-c pointer-events-auto">
<view class="top-header flex-row align-c" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true">
<image :src="avatar" class="avatar" mode="aspectFill"></image>
<view class="ml-10 flex-col">
<text class="nickname text-line-1">{{ live_data && live_data.title ? live_data.title : '直播' }}</text>
<text class="level">9999本场点赞</text>
</view>
</view>
<view class="flex-row align-c pointer-events-auto">
<view class="flex-row align-c" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true">
<view class="flex-row align-c pr" style="direction: rtl;">
<view v-for="(item, index) in viewers" :key="index" class="viewer-wrapper" :style="'z-index:' + (index + 1) + ';' + (index == 0 ? 'margin-right: 0;' : '')">
<image :src="item.avatar" class="viewer-avatar" mode="aspectFill"></image>
@ -28,7 +28,7 @@
<view class="flex-1 bottom-line-exclude-bottom flex-row">
<view class="flex-1 flex-col jc-e">
<view class="pr">
<view class="bulletin-area pr pointer-events-auto" :style="'width:' + (windowWidth - 150) + 'px;'">
<view class="bulletin-area pr" :style="'width:' + (windowWidth - 150) + 'px;'" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true">
<!-- #ifdef APP-NVUE -->
<!-- nvue 使用 list进行列表渲染 -->
<list class="bulletin-area" :style="'width:' + (windowWidth - 150) + 'px;'" :show-scrollbar="false" loadmoreoffset="30" @scroll="scroll_event" @loadmore="scroll_to_lower_event">
@ -99,7 +99,7 @@
<text class="cr-10 cr-red">{{ message_num }}条新消息</text>
</view>
</view>
<view v-if="!isEmpty(explain_goods)" class="explain-goods pointer-events-auto">
<view v-if="!isEmpty(explain_goods)" class="explain-goods" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true">
<image :src="explain_goods.goods_avatar" class="explain-goods-image" style="width: 198rpx;height: 198rpx;" mode="aspectFill"></image>
<view class="explain-goods-content mt-10" style="padding: 8rpx;box-sizing: border-box;">
<text class="explain-goods-name text-line-2 size-12">{{ explain_goods.goods_name }}</text>
@ -108,14 +108,14 @@
</view>
</view>
<!-- 底部谁来了的提示-->
<view v-if="is_user_comes" class="flex-row mt-3 pointer-events-auto" :style="'max-width:' + (windowWidth - 100) + 'px;'">
<view v-if="is_user_comes" class="flex-row mt-3" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true" :style="'max-width:' + (windowWidth - 100) + 'px;'">
<view class="user-comes flex-row">
<text class="user-name cr-blue">{{ commons_name }}</text>
<text class="user-name cr-d">来了</text>
</view>
</view>
<!-- 底部交互区域 -->
<view class="flex-row align-c mt-5 pointer-events-auto">
<view class="flex-row align-c mt-5" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true">
<view class="flex-1 bottom-actions-input">
<input :value="comment_value" type="text" confirm-type="done" :adjust-position="false" placeholder="说点什么" @focus="add_comment" @input="(e) => comment_value = e.detail.value" @confirm="comment_input_confirm" />
</view>
@ -134,17 +134,17 @@
</view>
</view>
<!-- 添加评论 -->
<view v-if="is_add_comment" class="keyboard-input pointer-events-auto" :style="'width:' + windowWidth + 'px;bottom:' + listener_height + 'px;'">
<view v-if="is_add_comment" class="keyboard-input" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true" :style="'width:' + windowWidth + 'px;bottom:' + listener_height + 'px;'">
<view class="input">
<input :value="comment_value" :focus="is_add_comment" type="text" confirm-type="done" :adjust-position="false" :auto-blur="true" placeholder="说点什么" @input="(e) => comment_value = e.detail.value" @blur="() => is_add_comment = false" @confirm="comment_input_confirm" />
</view>
</view>
<!-- 商品弹出框 -->
<component-popup ref="popupGoodsRef" mode="bottom" title="添加商品" class="pointer-events-auto" :closeable="true">
<component-popup ref="popupGoodsRef" mode="bottom" title="添加商品" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true" :closeable="true">
<component-goods isGoodsPopup></component-goods>
</component-popup>
<!-- 分享弹窗 -->
<component-share-popup ref="share" class="pointer-events-auto"></component-share-popup>
<component-share-popup ref="share" @dblclick="handle_double_click" @touchend="handle_touch_end" :data-ignore="true"></component-share-popup>
</view>
</template>
@ -576,6 +576,12 @@
});
}
},
handle_touch_end(event) {
this.$emit("handleTouchEnd", event);
},
handle_double_click(event) {
this.$emit("handleDoubleClick", event);
}
}
}
</script>

View File

@ -93,9 +93,12 @@ export default {
},
// 处理鼠标双击事件
handleDoubleClick(event) {
// 防抖处理100ms内只能触发一次
if (event.target.dataset.ignore) {
return;
}
// 防抖处理200ms内只能触发一次
const currentTime = Date.now();
if (currentTime - this.lastLikeTime < 100) {
if (currentTime - this.lastLikeTime < 200) {
return;
}
@ -108,14 +111,17 @@ export default {
// 处理触屏双击事件
handleTouchEnd(event) {
if (event.target.dataset.ignore) {
return;
}
// 获取当前位置
let x, y;
if (event.changedTouches && event.changedTouches.length > 0) {
x = event.changedTouches[0].clientX;
y = event.changedTouches[0].clientY;
x = event.changedTouches[0].screenX;
y = event.changedTouches[0].screenY;
} else {
x = event.clientX || 0;
y = event.clientY || 0;
x = event.screenX || 0;
y = event.screenY || 0;
}
const currentTime = new Date().getTime();
@ -124,12 +130,11 @@ export default {
Math.pow(x - this.lastTapPosition.x, 2) +
Math.pow(y - this.lastTapPosition.y, 2)
);
// 判断是否为双击 (300ms内且距离较近)
if (tapLength < 300 && tapLength > 0 && distance < 50) {
// 防抖处理,100ms内只能触发一次
if (currentTime - this.lastLikeTime < 100) {
// 防抖处理,200ms内只能触发一次
if (currentTime - this.lastLikeTime < 200) {
this.lastTapTime = currentTime;
this.lastTapPosition = { x, y };
return;

View File

@ -1,16 +1,16 @@
<template>
<view :class="theme_view + ' flex-row pr'" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'">
<view class="flex-1 pr" @dblclick="handleDoubleClick" @touchend="handleTouchEnd">
<view class="flex-1 pr">
<live-video ref="live-video" :src="live_config.pull_flv_url || 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'" @ended="ended"></live-video>
<!-- 简化版点赞效果组件 -->
<like-effect ref="likeEffect" :custom-images="like_show_imgs"></like-effect>
</view>
<view v-if="!is_loading" class="live-content" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'">
<view v-if="!is_loading" class="live-content" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'" @dblclick="handleDoubleClick" @touchend="handleTouchEnd" :data-ignore="false">
<template v-if="!is_live_ended">
<live-content :live-config="live_config" @live-back="live_back"></live-content>
<live-content :live-config="live_config" @live-back="live_back" @handleDoubleClick="handleDoubleClick" @handleTouchEnd="handleTouchEnd"></live-content>
<!-- 简化版点赞效果组件 -->
<like-effect ref="likeEffect" :custom-images="like_show_imgs" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'"></like-effect>
</template>
<template v-else>
<view class="live-ended flex-row align-c jc-c" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'">
<view class="live-ended flex-row align-c jc-c" :style="'width:' + windowWidth + 'px;height:' + windowHeight + 'px;'" @dblclick="handleDoubleClick" @touchend="handleTouchEnd" :data-ignore="true">
<view class="flex-col align-c">
<text style="color:#fff;font-size:16px;">直播已结束</text>
<button plain size="mini" class="mt-10 live-ended-button" @click="back"><text class="cr-f pa-5" @tap="live_back">退出直播间</text></button>
@ -51,7 +51,6 @@
width: 100%;
height: 100%;
background: transparent;
pointer-events: none;
}
.live-ended {
// 添加渐变背景色

View File

@ -1,13 +1,13 @@
<template>
<view :class="theme_view + ' live-bg'">
<view class="w h" @dblclick="handleDoubleClick" @touchend="handleTouchEnd">
<view class="w h">
<live-video ref="liveVideo" :src="live_config.pull_flv_url || 'http://live-pull-all.shopxo.vip/68f764013572f9240ca7ce6c/shopxo122.m3u8'" @ended="ended" @mutedAutoPlaySuccess="muted_auto_play_success"></live-video>
<!-- 简化版点赞效果组件 -->
<like-effect ref="likeEffect" :custom-images="like_show_imgs"></like-effect>
</view>
<view v-if="!is_loading" class="live-content">
<view v-if="!is_loading" class="live-content" @dblclick="handleDoubleClick" @touchend="handleTouchEnd">
<template v-if="!is_live_ended">
<live-content :live-config="live_config" :live-show-imgs="like_show_imgs" @live-back="live_back"></live-content>
<live-content :live-config="live_config" :live-show-imgs="like_show_imgs" @live-back="live_back" @handleDoubleClick="handleDoubleClick" @handleTouchEnd="handleTouchEnd"></live-content>
<!-- 简化版点赞效果组件 -->
<like-effect ref="likeEffect" :custom-images="like_show_imgs"></like-effect>
</template>
<template v-else>
<view class="live-ended flex-row align-c jc-c">
@ -73,7 +73,6 @@
z-index: 9;
width: 100%;
height: 100%;
pointer-events: none;
}
.live-muted {
position: absolute;