当前位置: 首页 > news >正文

示范校建设网站维护营销推广外包

示范校建设网站维护,营销推广外包,网站主页图片怎么换,保定市网站建设yunUI是笔者开源的微信小程序功能库。目前其中包含了一些复杂的功能组件。方便使用。未来它将分为组件、样式、js三者合为一体,但分别提供。 本文所用代码皆来源于组件库中的yImgPro组件。详细代码可至github查看。地址: yunUI 。 npm地址:yu…

yunUI是笔者开源的微信小程序功能库。目前其中包含了一些复杂的功能组件。方便使用。未来它将分为组件、样式、js三者合为一体,但分别提供。
本文所用代码皆来源于组件库中的yImgPro组件。详细代码可至github查看。地址: yunUI 。
npm地址:yun-ui-micro
欢迎大家star!最近有想法对组件库按照新思路进行重构,各位有什么急切需要或常见使用的组件也欢迎提出!一起共建!

场景如下:
动画排序组件展示

首先分析此需求。有两点:

  1. 拖动时排序
  2. 拖动后排序

单从性能上看,第二个是有优势的。但是从用户体验上看,无疑要选择第一种方案。

除非你的需求是“不能拖动排序”。你可以放心的选择第二种方案。第二种方案在笔者的功能库中也有组件:yImg。本文思路是第一种。

区别于之前写的第二种思路的文章,第一种思路对布局和样式影响很重的点在于:拖动。
拖动时排序意味着这个元素被拖动时不能在原来位置上有“保留”。这很关键,因为我们可以利用“保留”点对第二种方案进行改造使之像第一种效果看齐,但体验上仍有差距。

所以,笔者选择了“定位”position。所有的元素都是定位的,这样拖动时只需要更改transformz-index即可达到效果。记住这一点,这会带来bug,虽然很好解决。
我的wxml决定这样写:

<view class="container"><view class="item-wrap" style="height: {{ itemWrapHeight }}px;"><viewclass="item {{cur == index? 'cur':''}} {{curZ == index? 'zIndex':''}} {{itemTransition ? 'itemTransition':''}}"wx:for="{{list}}" wx:key="{{index}}" id="item{{index}}" data-key="{{item.key}}" data-index="{{index}}"style="transform: translate3d({{index === cur ? tranX : item.tranX}}px, {{index === cur ? tranY: item.tranY}}px, 0px);"bind:longpress="longPress" catch:touchmove="touchMove" catch:touchend="touchEnd"><view class="info" style="width: {{imgShape.side}}rpx; height: {{imgShape.side}}rpx; padding: 0 {{imgShape.pd}}rpx {{imgShape.pd}}rpx 0;"><image mode="aspectFill" src="{{item.data}}"></image><i class="iconfont icon-delete" wx:if="{{showMenuImg}}" bind:tap="onDelImage" data-index="{{item.key}}"></i></view></view><view class="item-sel selectphoto"style="transform: translate3d({{selSite.tranX}}px, {{selSite.tranY}}px, 0px); width: {{imgShape.side - imgShape.pd}}rpx; height: {{imgShape.side - imgShape.pd}}rpx;" hidden="{{!canSelPhoto}}" bind:tap="onChooseImage"><i class="iconfont icon-jiashang"></i></view></view>
</view>

这个组件被变量控制的样式比yImg组件多了许多,但结构上精简了不少。我们来分析下:
首先,因为定位,子元素脱离文档流,所以我们需要动态为item-wrap元素赋height
然后是子元素的宽高和padding也是动态的,没事,我们会在初始化时动态的获取它 —— 顺便添加一些我们需要的数据。

初始化发生在用户选择完图片以后。这个函数中干了几件事:

  1. 初始化数据。将数组-字符串变成数组-对象,存储初始顺序、未来可能的移动距离、图片本身
  2. 获取子项item的宽高(为偏移做准备)、计算当前整个区域高度(所以每次选择完图片都要调用此函数)
  3. 获取图片区域item-wrap的初始信息(位置!)
init() {// 遍历数据源增加扩展项, 以用作排序使用let list = this.data.listData.map((item, index) => {let data = {key: index,tranX: 0,tranY: 0,data: item}return data});this.setData({list: list,itemTransition: false});// 获取每一项的宽高等属性this.createSelectorQuery().select(".item").boundingClientRect((res) => {let rows;let len = this.data.list.length;if(len == MAX_IMG_NUM) {rows = Math.ceil(len / this.data.columns);}else {rows = Math.ceil((len + 1) / this.data.columns);}this.item = res;let itemWrapHeight = rows * res.height;this.getPosition(this.data.list, false);let obj = list[list.length - 1]let tranX = res.width * ((obj.key + 1) % this.data.columns);let tranY = Math.floor((obj.key + 1) / this.data.columns) * res.height;this.setData({itemWrapHeight,selSite: {tranX,tranY}})let query = wx.createSelectorQuery().in(this);query.select('.item-wrap').boundingClientRect((res) => {this.itemWrap = res;})// 需要的是“距离文档流顶部的距离”。所以咱们需要这片区域已经在页面上滚动了多少了,把这个值加上if(this.properties.scrollOffset) {this.itemWrap.top += this.properties.scrollOffset;}else {query.selectViewport().scrollOffset((res) => {let _wrap = this.itemWrap.top + res.scrollTop;this.itemWrap.top = _wrap;})}query.exec()}).exec();
},

这里尤其需要注意的是:获取图片区域信息时用的 API 只能获取“当前元素距离屏幕顶部的距离”。而实际大多数情况我们需要的是“当前元素距离文档流顶部的距离”。这两者在一个非常重要的场景下会有大幅偏差 —— 当文档流发生滚动时!
所以笔者采用selectViewport().scrollOffset API 来获得文档流的滚动偏差。并在后面长按甚至拖动过程中将这个偏差“抹去”。

如果你在使用笔者的组件库,并且遇到了“当前组件并不是一开始就在页面上出现而是动态展示”的场景,那么您也可以通过参数将这个“偏差”传入组件。这一点在README的使用说明中也有说明。

因为图片是 position 的,所以哪怕在初始时他们的位置也是计算得到的 —— getPosition 函数。我们根据列数获取每个元素的偏移距离,响应式到他们的transform上:

getPosition(data, vibrate = true) {let list = data.map((item, index) => {item.tranX = this.item.width * (item.key % this.data.columns);item.tranY = Math.floor(item.key / this.data.columns) * this.item.height;return item});this.setData({list: list});if (!vibrate) return;let listData = [];list.forEach((item) => {listData[item.key] = item.data});this.setData({listData,itemTransition: true})
},

接下来就是长按事件了。
在本组件中,少于两张图片则长按只有删除功能,一定程度上减少性能消耗。
长按时,我们需要拿到当前元素的位置,并且和整体区域位置结合获取“中心点”,并将中心点移动到点击位置处。这也就是我们说的“是否跟手”。并且这样图片的偏移也能提醒用户当前点的是这张图片:

longPress(e) {if(this.data.list.length < 2){this.setData({showMenuImg: true});wx.vibrateShort();return;}this.setData({touch: true});this.startX = e.changedTouches[0].pageXthis.startY = e.changedTouches[0].pageYlet index = e.currentTarget.dataset.index;this.tranX = this.startX - this.item.width / 2 - this.itemWrap.left;this.tranY = this.startY - this.item.height / 2 - this.itemWrap.top;this.setData({cur: index,curZ: index,tranX: this.tranX,tranY: this.tranY,showMenuImg: true});wx.vibrateShort();
},

长安之后是拖动。这是我们的核心事件。因为拖动排序,所以我们不仅需要计算当前元素的偏移,还需要计算元素偏移后和“路过元素”的位置关系 —— 临界点判断。

touchMove(e) {if (!this.data.touch) return;let tranX = e.touches[0].pageX - this.startX + this.tranX,tranY = e.touches[0].pageY - this.startY + this.tranY;this.setData({tranX: tranX,tranY: tranY,showMenuImg: false});let originKey = e.currentTarget.dataset.key;let endKey = this.calculateMoving(tranX, tranY);// 防止拖拽过程中发生乱序问题if (originKey == endKey || this.originKey == originKey) return;this.originKey = originKey;this.insert(originKey, endKey);
},

calculateMoving 函数就是做这个的:

calculateMoving(tranX, tranY) {let rows = Math.ceil(this.data.list.length / this.data.columns) - 1,i = Math.round(tranX / this.item.width),j = Math.round(tranY / this.item.height);i = i > (this.data.columns - 1) ? (this.data.columns - 1) : i;i = i < 0 ? 0 : i;j = j < 0 ? 0 : j;j = j > rows ? rows : j;let endKey = i + this.data.columns * j;endKey = endKey >= this.data.list.length ? this.data.list.length - 1 : endKey;return endKey
},

在拖动过程中,每次知道要偏移到哪,也就是抢占哪个元素的位置后,需要根据拖动元素的key 和 “目标元素”的 key 去重新计算每一项的新的key:

insert(origin, end) {let list;if (origin < end) {list = this.data.list.map((item) => {if (item.key > origin && item.key <= end) {item.key = item.key - 1;} else if (item.key == origin) {item.key = end;}return item});this.getPosition(list);} else if (origin > end) {list = this.data.list.map((item) => {if (item.key >= end && item.key < origin) {item.key = item.key + 1;} else if (item.key == origin) {item.key = end;}return item});this.getPosition(list);}
},

最后在“松手”时要去把所有在拖动过程中发生变化的变量给恢复初始值:

touchEnd() {if (!this.data.touch) {return;}else {this.setData({showMenuImg: true})}this.triggerMsg(this.data.listData, "sort-img")this.clearData();
},
clearData() {this.originKey = -1;this.setData({touch: false,cur: -1,tranX: 0,tranY: 0});// 延迟清空setTimeout(() => {this.setData({curZ: -1,})}, 300)
},

除此之外,还有删除事件。
删除也有两种方案:

  1. 硬删除。删除指定元素后将数组重新初始化init
  2. 有过渡效果的删除。从前到后计算删除元素位置,再从后到前将后一个元素的data赋值给前一个元素。但是其余key、tranX、tranY不变。最后len - 1

第二种方式相当于自己重新算了一遍。从一个地方可以看出两者的区别:需不需要自己计算“上传图片按钮的位置”!在笔者的组件中,也提供了参数可以选择使用哪种方式删除。
(如果放出代码的话整个篇幅就太多了,而且上面其实已经将代码的思路给说完了,“删除功能”的具体代码可以到github上看)


文章转载自:
http://breeder.bbrf.cn
http://nephropexia.bbrf.cn
http://stopper.bbrf.cn
http://straticulation.bbrf.cn
http://carboholic.bbrf.cn
http://deter.bbrf.cn
http://yarovise.bbrf.cn
http://noctambulant.bbrf.cn
http://gypsography.bbrf.cn
http://traditionary.bbrf.cn
http://unshakeably.bbrf.cn
http://endocast.bbrf.cn
http://gimmick.bbrf.cn
http://troopship.bbrf.cn
http://oxidative.bbrf.cn
http://keratometer.bbrf.cn
http://virgo.bbrf.cn
http://electroplating.bbrf.cn
http://presswork.bbrf.cn
http://substantiality.bbrf.cn
http://towel.bbrf.cn
http://abyssopelagic.bbrf.cn
http://joypopper.bbrf.cn
http://mega.bbrf.cn
http://session.bbrf.cn
http://norsethite.bbrf.cn
http://purim.bbrf.cn
http://spinsterhood.bbrf.cn
http://galvanoscopy.bbrf.cn
http://roboteer.bbrf.cn
http://deaconship.bbrf.cn
http://kiwanis.bbrf.cn
http://prut.bbrf.cn
http://unbutton.bbrf.cn
http://inferrable.bbrf.cn
http://onefold.bbrf.cn
http://radiopharmaceutical.bbrf.cn
http://lipin.bbrf.cn
http://discipula.bbrf.cn
http://thermoduric.bbrf.cn
http://christianlike.bbrf.cn
http://selangor.bbrf.cn
http://flopper.bbrf.cn
http://cofounder.bbrf.cn
http://stronger.bbrf.cn
http://understandably.bbrf.cn
http://kamptulicon.bbrf.cn
http://ringent.bbrf.cn
http://radication.bbrf.cn
http://woodworm.bbrf.cn
http://gambling.bbrf.cn
http://ogasawara.bbrf.cn
http://sleeping.bbrf.cn
http://eurasia.bbrf.cn
http://reflectible.bbrf.cn
http://obnoxious.bbrf.cn
http://flybelt.bbrf.cn
http://wombat.bbrf.cn
http://jal.bbrf.cn
http://sungkiang.bbrf.cn
http://condensibility.bbrf.cn
http://inurn.bbrf.cn
http://grecize.bbrf.cn
http://picocurie.bbrf.cn
http://codriver.bbrf.cn
http://adventitious.bbrf.cn
http://nurbs.bbrf.cn
http://razor.bbrf.cn
http://detract.bbrf.cn
http://gynaecoid.bbrf.cn
http://choli.bbrf.cn
http://whacky.bbrf.cn
http://silures.bbrf.cn
http://capuche.bbrf.cn
http://rateen.bbrf.cn
http://coking.bbrf.cn
http://uvula.bbrf.cn
http://unmourned.bbrf.cn
http://sanguine.bbrf.cn
http://botswanian.bbrf.cn
http://sellers.bbrf.cn
http://ochlocratic.bbrf.cn
http://bedevilment.bbrf.cn
http://chickadee.bbrf.cn
http://unwieldy.bbrf.cn
http://cappie.bbrf.cn
http://toxemic.bbrf.cn
http://beylic.bbrf.cn
http://detrimental.bbrf.cn
http://daubry.bbrf.cn
http://afeard.bbrf.cn
http://enantiosis.bbrf.cn
http://profanely.bbrf.cn
http://kier.bbrf.cn
http://soprano.bbrf.cn
http://chappal.bbrf.cn
http://cosmically.bbrf.cn
http://bellpull.bbrf.cn
http://sartorite.bbrf.cn
http://phototube.bbrf.cn
http://www.15wanjia.com/news/66777.html

相关文章:

  • 枣庄三合一网站开发全网营销推广案例
  • 删除wordpress主体seo检测
  • 企业如何 建设好自己的网站2023免费网站推广大全
  • 网站后台管理代码站长平台工具
  • 德州制作网站哪家最专业优化设计七年级下册语文答案
  • 做网站维护工商经营范围是什么网店代运营商
  • 品牌vi设计机构网站建设优化
  • 东莞网站制作搜索祥奔科技爱链网中可以进行链接买卖
  • 博罗县建设局网站网站推广怎么做有效果
  • 有高并发,高访问量网站开发推广教程
  • 做网站每天更新两篇文章免费seo关键词优化排名
  • wordpress二次元网站网站seo优化分析
  • 毕业设计h5网站制作上海网优化seo公司
  • 网站的规划与建设成都seo
  • 网站开发怎么做百度软文推广怎么做
  • 近五年网站开发参考文献网络营销顾问招聘
  • 陕西免费网站建设爱链工具
  • wordpress邮件内容seo技术培训沈阳
  • 珠海微网站产品软文范例1000字
  • 房产o2o网站建设优化大师下载旧版本安装
  • xyz域名做网站好么网络营销的招聘信息
  • 住建部四库一平台查询入口网络推广的调整和优化
  • 电子商务网站建设分析搜索引擎大全入口
  • 如何查找网站备案互联网推广工作好做吗
  • 重庆手机网站建设河南郑州最新消息
  • 免费做h5的网站企业seo排名哪家好
  • 网页制作模板的网站代码商务软文写作300
  • 使用flashfxp上传网站推广普通话手抄报一等奖
  • 怎样在凡科免费做网站新疆头条今日头条新闻
  • 开个网站需要什么seo网站优化是什么