Commit 774db429 by 李嘉林

小程序商品列表堆叠卡片样式

parent 3579d1b3
<!-- 商品列表item --> <!-- 商品列表item -->
<view class="goodsItem {{datas.componentData.style==='rowList'?'goodsRowList':''}}" style="--proGap2:{{datas.componentData.proGap*2}}rpx;"> <view class="goodsItem {{datas.componentData.style==='rowList'?'goodsRowList':''}} {{datas.componentData.style==='heap'?'goodsRowList goodsHeapItem':''}}" style="--proGap2:{{datas.componentData.proGap*2}}rpx;">
<view class="goods-item-child {{datas.componentData['borderColorShow']?'goods-item-child-bd':''}}" style="border-radius:{{datas.componentData.borderRadius}}em;--border_color:{{datas.componentData['borderColor']}};box-shadow:{{datas.componentData['cardShadow']?'0rpx 0rpx 10rpx '+datas.componentData['cardShadowSize']*2+'rpx #ccc':''}};"> <view class="goods-item-child {{datas.componentData['borderColorShow']?'goods-item-child-bd':''}}" style="border-radius:{{datas.componentData.borderRadius}}em;--border_color:{{datas.componentData['borderColor']}};box-shadow:{{datas.componentData['cardShadow']?'0rpx 0rpx 10rpx '+datas.componentData['cardShadowSize']*2+'rpx #ccc':''}};">
<!-- 商户入口-顶部 --> <!-- 商户入口-顶部 -->
<view class="merchantsEntrance flex" wx:if="{{datas.componentData['merchantsEntrance'] && datas.componentData['merchantsEntranceType'] == 0}}"> <view class="merchantsEntrance flex" wx:if="{{datas.componentData['merchantsEntrance'] && datas.componentData['merchantsEntranceType'] == 0 && datas.componentData.style!='heap'}}">
<view class="left flex" wx:if="{{items != null}}"> <view class="left flex" wx:if="{{items != null}}">
<view class="logo"> <view class="logo">
<image mode='widthFix' src="{{items.shopLogoUrl}}" /> <image mode='widthFix' src="{{items.shopLogoUrl}}" />
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
style="padding:{{datas.componentData.imgSize}}" style="padding:{{datas.componentData.imgSize}}"
> >
<!-- 开启售卖 --> <!-- 开启售卖 -->
<view class="saleWay" wx:if="{{items.saleWay==2 && items.getSaleTime>0}}"> <view class="saleWay" wx:if="{{items.saleWay==2 && items.getSaleTime>0 && datas.componentData.style!='heap'}}">
<view class="saleWayBg"></view> <view class="saleWayBg"></view>
<view class="saleTime"> <view class="saleTime">
<van-count-down <van-count-down
...@@ -49,13 +49,13 @@ ...@@ -49,13 +49,13 @@
</view> </view>
<!-- 商品主图 --> <!-- 商品主图 -->
<image <image
mode="{{datas.componentData.style==='rowList'?'aspectFit':'widthFix'}}" mode="{{datas.componentData.style==='rowList' || datas.componentData.style==='heap'?'aspectFit':'widthFix'}}"
class="productImgUrl" class="productImgUrl"
wx:if="{{datas.componentData.goodsImgType == 1}}" wx:if="{{datas.componentData.goodsImgType == 1}}"
src="{{items.productImgUrl}}" src="{{items.productImgUrl}}"
/> />
<image <image
mode="{{datas.componentData.style==='rowList'?'aspectFit':'widthFix'}}" mode="{{datas.componentData.style==='rowList' || datas.componentData.style==='heap'?'aspectFit':'widthFix'}}"
class="productImgUrl" class="productImgUrl"
wx:else wx:else
src="{{items.coverImage}}" src="{{items.coverImage}}"
...@@ -187,7 +187,7 @@ ...@@ -187,7 +187,7 @@
</block> </block>
</view> </view>
<!-- 商户入口二 --> <!-- 商户入口二 -->
<view class="merchantsEntrance flex" wx:if="{{datas.componentData.merchantsEntrance&&datas.componentData.merchantsEntranceType==1}}"> <view class="merchantsEntrance flex" wx:if="{{datas.componentData.merchantsEntrance&&datas.componentData.merchantsEntranceType==1 && datas.componentData.style!='heap'}}">
<view class="left flex" wx:if="{{items!=null}}"> <view class="left flex" wx:if="{{items!=null}}">
<view class="logo"> <view class="logo">
<image mode='widthFix' src="http://test-bucket-ant.oss-cn-shanghai.aliyuncs.com/product/ppefWK8BS6.png?x-oss-process=image/resize,limit_1,w_150,h_150" /> <image mode='widthFix' src="http://test-bucket-ant.oss-cn-shanghai.aliyuncs.com/product/ppefWK8BS6.png?x-oss-process=image/resize,limit_1,w_150,h_150" />
......
...@@ -40,6 +40,9 @@ align-items: flex-start; ...@@ -40,6 +40,9 @@ align-items: flex-start;
flex-direction: column; flex-direction: column;
justify-content: space-around; justify-content: space-around;
} }
.goodsHeapItem{
width: 100%;
}
.merchantsEntrance{ .merchantsEntrance{
padding: 8rpx 20rpx; padding: 8rpx 20rpx;
......
import TouchEvent from "./utils/touchEvent";
const componentOptions = {
// 组件选项
options: {
multipleSlots: true
},
behaviors: [],
properties: {
datas: {
type: Object
}
},
// 组件数据
data: {
isPageHidden: false, // 页面是否处于隐藏状态
isLoading: false,
swiperCurIndex: 0,
slideClass: "",
lockSwipe: false
},
// 数据监听器
observers: {},
// 组件生命周期
lifetimes: {
created() {
new TouchEvent(this, "touchCard", {
swipe: evt => {
//在touch结束触发,evt.direction代表滑动的方向 ['Up','Right','Down','Left']
if (evt.direction === "Left") this.next(evt);
if (evt.direction === "Right") this.prev(evt);
}
});
},
attached() {}
},
// 组件方法
methods: {
next(e) {
if (this.data.lockSwipe) return;
this.data.lockSwipe = true;
if (-this.data.swiperCurIndex >= this.data.datas.componentData.goodsList.length - 1) {
return (this.data.lockSwipe = false);
}
const index = e.currentTarget.dataset["index"];
this.setData(
{ ["datas.componentData.goodsList[" + index + "].slideClass"]: " ani-slide-up" },
() => {
this.setData({
swiperCurIndex: --this.data.swiperCurIndex
});
}
);
setTimeout(() => {
this.data.lockSwipe = false;
this.setData({
["datas.componentData.goodsList[" + index + "].slideClass"]: ""
});
}, 590);
},
prev(e) {
const index = e.currentTarget.dataset["index"] - 1;
if (this.data.lockSwipe || index < 0) return;
this.data.lockSwipe = true;
this.setData({
["datas.componentData.goodsList[" + index + "].slideClass"]: " ani-slide-down",
swiperCurIndex: ++this.data.swiperCurIndex
});
setTimeout(() => {
this.data.lockSwipe = false;
this.setData({
["datas.componentData.goodsList[" + index + "].slideClass"]: ""
});
}, 590);
}
},
definitionFilter() {},
// 页面生命周期
pageLifetimes: {
// 页面被展示
show() {
const { isPageHidden } = this.data;
// show事件发生前,页面不是处于隐藏状态时
if (!isPageHidden) {
return;
}
// 重新执行定时器等操作
},
// 页面被隐藏
hide() {
this.setData({
isPageHidden: true
});
// 清除定时器等操作
},
// 页面尺寸变化时
resize() {}
}
};
Component(componentOptions);
{
"component": true,
"usingComponents": {
"goods-item": "../GoodsItem/index"
}
}
<view class="container center">
<view class="card-swiper">
<view
wx:for="{{datas.componentData.goodsList}}"
wx:key="index"
data-index="{{index}}"
class="{{'card-swiper-item curdistance' + (swiperCurIndex + index) + (!!item.slideClass? item.slideClass: '')}}"
bindtap="next"
catchtouchstart="touchCard.start"
catchtouchmove="touchCard.move"
catchtouchend="touchCard.end"
catchtouchcancel="touchCard.cancel"
>
<goods-item
style="width:100%"
datas="{{datas}}"
items="{{datas.componentData.goodsList[index]}}"
indexs="{{index}}"
></goods-item>
</view>
</view>
</view>
.container{
width: 100%;
height: 200rpx;
padding: 0 0 20rpx;
}
/**index.wxss**/
.card-swiper{
position: relative;
width: 100%;
height: 100%;
color: #666;
font-size: 28rpx;
}
.card-swiper-item{
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 92%;
transition: all .3s ease-out;
z-index: 0;
display: none;
overflow: hidden;
}
.card-swiper .card-swiper-item.curdistance0{
z-index: 10;
display: flex;
}
.card-swiper .card-swiper-item.curdistance1{
display: flex;
z-index: 9;
transform: scale(.95);
opacity: .7;
left: 40rpx;
}
.card-swiper .card-swiper-item.curdistance2{
display: flex;
z-index: 8;
transform: scale(.9);
opacity: .4;
left: 80rpx;
}
.ani-slide-up{
display: flex;
animation: slideUp .6s ease-out;
z-index: 11;
/* transform: rotate(25deg); */
}
.ani-slide-down{
display: flex;
animation: slideUp .6s ease-in;
animation-direction: reverse;
}
@keyframes slideUp{
0% {
}
70% {
opacity: 1;
}
100% {
transform: translateX(-1000rpx);
opacity: 0;
-webkit-transform: translateX(-1000rpx);
-moz-transform: translateX(-1000rpx);
-ms-transform: translateX(-1000rpx);
-o-transform: translateX(-1000rpx);
}
}
\ No newline at end of file
var defaultOption = {
touchStart: function () { },
touchMove: function () { },
touchEnd: function () { },
touchCancel: function () { },
multipointStart: function () { },
multipointEnd: function () { },
tap: function () { },
doubleTap: function () { },
longTap: function () { },
singleTap: function () { },
rotate: function () { },
pinch: function () { },
pressMove: function () { },
swipe: function () { }
}
export default class YrobotTouch {
constructor(pageOBJ, name, option = {}) {
this.preV = { x: null, y: null };
this.pinchStartLen = null;
this.scale = 1;
this.isDoubleTap = false;
this.delta = null;
this.last = null;
this.now = null;
this.tapTimeout = null;
this.singleTapTimeout = null;
this.longTapTimeout = null;
this.swipeTimeout = null;
this.x1 = this.x2 = this.y1 = this.y2 = null;
this.preTapPosition = { x: null, y: null };
this.lastZoom = 1;
this.tempZoom = 1;
try {
if (this._checkBeforeCreate(pageOBJ, name)) {
this._name = name
this._option = { ...defaultOption, ...option }
pageOBJ[name] = this
this._bindFunc(pageOBJ)
}
} catch (error) {
console.error(error)
}
}
_checkBeforeCreate(pageOBJ, name) {
if (!pageOBJ || !name) {
throw new Error('YrobotTouch实例化时,必须传入page对象和引用名')
return false
}
if (pageOBJ[name]) {
throw new Error('YrobotTouch实例化error: ' + name + ' 已经存在page中')
return false
}
return true
}
_bindFunc(pageOBJ) {
let funcNames = ['start', 'move', 'end', 'cancel']
for (let funcName of funcNames)
pageOBJ[this._name + '.' + funcName] = this[funcName].bind(this)
}
start(evt) {
if (!evt.touches) return;
this.now = Date.now();
this.x1 = evt.touches[0].pageX == null ? evt.touches[0].x : evt.touches[0].pageX;
this.y1 = evt.touches[0].pageY == null ? evt.touches[0].y : evt.touches[0].pageY;
this.delta = this.now - (this.last || this.now);
this._option.touchStart(evt);
if (this.preTapPosition.x !== null) {
this.isDoubleTap = (this.delta > 0 && this.delta <= 250 && Math.abs(this.preTapPosition.x - this.x1) < 30 && Math.abs(this.preTapPosition.y - this.y1) < 30);
}
this.preTapPosition.x = this.x1;
this.preTapPosition.y = this.y1;
this.last = this.now;
let preV = this.preV,
len = evt.touches.length;
if (len > 1) {
this._cancelLongTap();
this._cancelSingleTap();
let otx = evt.touches[1].pageX == null ? evt.touches[1].x : evt.touches[1].pageX;
let oty = evt.touches[1].pageY == null ? evt.touches[1].y : evt.touches[1].pageY;
let v = { x: otx - this.x1, y: oty - this.y1 };
preV.x = v.x;
preV.y = v.y;
this.pinchStartLen = getLen(preV);
this._option.multipointStart(evt);
}
this.longTapTimeout = setTimeout(function () {
evt.type = "longTap";
this._option.longTap(evt);
}.bind(this), 750);
}
move(evt) {
if (!evt.touches) return;
let preV = this.preV,
len = evt.touches.length,
currentX = evt.touches[0].pageX == null ? evt.touches[0].x : evt.touches[0].pageX,
currentY = evt.touches[0].pageY == null ? evt.touches[0].y : evt.touches[0].pageY;
this.isDoubleTap = false;
if (len > 1) {
let otx = evt.touches[1].pageX == null ? evt.touches[1].x : evt.touches[1].pageX;
let oty = evt.touches[1].pageY == null ? evt.touches[1].y : evt.touches[1].pageY;
let v = { x: otx - currentX, y: oty - currentY };
if (preV.x !== null) {
if (this.pinchStartLen > 0) {
evt.singleZoom = getLen(v) / this.pinchStartLen;
evt.zoom = evt.singleZoom * this.lastZoom;
this.tempZoom = evt.zoom;
evt.type = "pinch";
this._option.pinch(evt);
}
evt.angle = getRotateAngle(v, preV);
evt.type = "rotate";
this._option.rotate(evt);
}
preV.x = v.x;
preV.y = v.y;
} else {
if (this.x2 !== null) {
evt.deltaX = currentX - this.x2;
evt.deltaY = currentY - this.y2;
} else {
evt.deltaX = 0;
evt.deltaY = 0;
}
this._option.pressMove(evt);
}
this._option.touchMove(evt);
this._cancelLongTap();
this.x2 = currentX;
this.y2 = currentY;
if (len > 1) {
// evt.preventDefault();
}
}
end(evt) {
if (!evt.changedTouches) return;
this._cancelLongTap();
let self = this;
evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2); //在结束钩子都加入方向判断,但触发swipe瞬时必须位移大于30
if (evt.touches.length < 2) {
this.lastZoom = this.tempZoom;
this._option.multipointEnd(evt);
}
this._option.touchEnd(evt);
//swipe
if ((this.x2 && Math.abs(this.x1 - this.x2) > 30) ||
(this.y2 && Math.abs(this.y1 - this.y2) > 30)) {
// evt.direction = this._swipeDirection(this.x1, this.x2, this.y1, this.y2);
this.swipeTimeout = setTimeout(function () {
evt.type = "swipe";
self._option.swipe(evt);
}, 0)
} else {
this.tapTimeout = setTimeout(function () {
evt.type = "tap";
self._option.tap(evt);
// trigger double tap immediately
if (self.isDoubleTap) {
evt.type = "doubleTap";
self._option.doubleTap(evt);
clearTimeout(self.singleTapTimeout);
self.isDoubleTap = false;
}
}, 0)
if (!self.isDoubleTap) {
self.singleTapTimeout = setTimeout(function () {
self._option.singleTap(evt);
}, 250);
}
}
this.preV.x = 0;
this.preV.y = 0;
this.scale = 1;
this.pinchStartLen = null;
this.x1 = this.x2 = this.y1 = this.y2 = null;
}
cancel(evt) {
clearTimeout(this.singleTapTimeout);
clearTimeout(this.tapTimeout);
clearTimeout(this.longTapTimeout);
clearTimeout(this.swipeTimeout);
this._option.touchCancel(evt);
}
_cancelLongTap() {
clearTimeout(this.longTapTimeout);
}
_cancelSingleTap() {
clearTimeout(this.singleTapTimeout);
}
_swipeDirection(x1, x2, y1, y2) {
return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
}
destroy() {
if (this.singleTapTimeout) clearTimeout(this.singleTapTimeout);
if (this.tapTimeout) clearTimeout(this.tapTimeout);
if (this.longTapTimeout) clearTimeout(this.longTapTimeout);
if (this.swipeTimeout) clearTimeout(this.swipeTimeout);
this._option.rotate = null;
this._option.touchStart = null;
this._option.multipointStart = null;
this._option.multipointEnd = null;
this._option.pinch = null;
this._option.swipe = null;
this._option.tap = null;
this._option.doubleTap = null;
this._option.longTap = null;
this._option.singleTap = null;
this._option.pressMove = null;
this._option.touchMove = null;
this._option.touchEnd = null;
this._option.touchCancel = null;
this.preV = this.pinchStartLen = this.scale = this.isDoubleTap = this.delta = this.last = this.now = this.tapTimeout = this.singleTapTimeout = this.longTapTimeout = this.swipeTimeout = this.x1 = this.x2 = this.y1 = this.y2 = this.preTapPosition = this.rotate = this.touchStart = this.multipointStart = this.multipointEnd = this.pinch = this.swipe = this.tap = this.doubleTap = this.longTap = this.singleTap = this.pressMove = this.touchMove = this.touchEnd = this.touchCancel = null;
return null;
}
}
function getLen(v) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
function dot(v1, v2) {
return v1.x * v2.x + v1.y * v2.y;
}
function getAngle(v1, v2) {
let mr = getLen(v1) * getLen(v2);
if (mr === 0) return 0;
let r = dot(v1, v2) / mr;
if (r > 1) r = 1;
return Math.acos(r);
}
function cross(v1, v2) {
return v1.x * v2.y - v2.x * v1.y;
}
function getRotateAngle(v1, v2) {
let angle = getAngle(v1, v2);
if (cross(v1, v2) > 0) {
angle *= -1;
}
return angle * 180 / Math.PI;
}
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
"component": true, "component": true,
"usingComponents": { "usingComponents": {
"goods-item":"./GoodsItem/index", "goods-item":"./GoodsItem/index",
"waterfall-flow":"../module/WaterfallFlow/index" "waterfall-flow":"../module/WaterfallFlow/index",
"heap-item":"./heapItem/index"
} }
} }
...@@ -84,6 +84,11 @@ ...@@ -84,6 +84,11 @@
></goods-item> ></goods-item>
</view> </view>
</view> </view>
<!-- 堆叠卡片 -->
<view class="goods-heap-Item" wx:if="{{datas.componentData.style==='heap'}}">
<heap-item datas="{{datas}}"></heap-item>
</view>
</view> </view>
</view> </view>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment