CSS 背景图片百分比及应用
适用于rpx雪碧图标中背景图片精准定位
百分比计算公式
任何CSS属性值为百分比时,都需要根据某个参考值进行计算,搞明白这个参考值是什么,理解就容易多了。
标准规定:background-position:percent的参考值x为:百分比为background-position-x的值 = (背景在雪碧中的左边宽度)/(容器宽度 – 背景图片宽度)*100%。
举个例子:
百度分享中有四个图标(大小设置是0.72rem0.72rem),我把这四个小图标扣到一张大小为(0.72rem3.65rem)的背景图,宽度跟图标是一样的,高度则为四个图片+1倍的高度,主要是为了后面的高度百分比成正比。
那么我们可以得到这张小图片的样式为:
.icon{
width:.72rem;
height:.72rem;
backgorund:url(img/sprite.png) no-repeat center top;
background-size:100%; //cover
background-position:0 0
}
.icon1{
backgorund-position:0 0;
}
.icon2{
background-position:0 -73/(73 - 365)*100%=25%
}
.icon3{
background-position:0 -146/(73-365)*100%=50%
}
.icon4{
background-position:0 -219/(73-365)*100%=75%
}
最关键是要理解上面这个计算方式。其实我们如果换另一大家都熟悉的常见定位就清楚了。
.icon2{
background-position:0 -0.73rem; (这个距离就是图标距离背景图片中的偏离值)
}
无限加载的两种处理
- 利用scroll-view组件自带的滑到底部触发函数
- 利用page函数上拉触底onReachBottom
第一种
<scroll-view bindscrolltolower="scrollBottom"></scroll-view>
Page({
scrollBottom:function(){
console.log('滚动到底部了');
}
})
第二种
Page({
onReachBottom:function(){
console.log('滚动到底部了');
}
})
swiper多栏切换无限加载
- 使用swiper+scroll-view结合
- 使用touch事件
第一种
<swiper>
<block for="{{list}}">
<swiper-item>
<scroll-view class="list" scroll-y="true" bindscrolltolower="loadMoreList">
<block for="{{list[item]}}">
<view class="item">
</view>
</block>
</scroll-view>
</swiper-item>
</block>
</swiper>
第二种
https://github.com/we-plugin/we-swiper
隐藏滚动条
内外层固定宽高,scroll-view添加padding或者把高度设为比外层的高度高。
<view class="tab">
<view class="tab-inner">
<scroll-view class="scroll-bangdan" scroll-x="true" scroll-left="{{scrollLeft}}">
<view class="ctrl" style="width:1054rpx">
<block wx:for="{{nav}}" wx:key="{{item.columnId}}">
<view class="toc{{current==index?' cur':''}}" bindtap="changeTab" data-index="{{index}}">
<view class="text">
<text>{{item.columnName}}</text>
</view>
</view>
</block>
</view>
</scroll-view>
<view class="mask"></view>
</view>
</view>
CSS 代码
.tab {
/* position: fixed;
left: 0;
top: 0; */
border-bottom: 1px solid #f8f8f8;
background: #fff;
z-index: 1;
width: 100%;
height: 100rpx;
line-height: 100rpx;
}
.tab-inner {
height: 100rpx;
overflow: hidden;
}
.scroll-bangdan {
width: 100%;
position: relative;
height: 130rpx;
}
.tab .ctrl {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
flex-flow: row wrap;
-webkit-flex: row wrap;
font-size: 28rpx;
height: 100rpx;
line-height: 100rpx;
}
第二种直接加下面的代码:
/* 去掉默认滚动条 */
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
订阅发布模式
支持先订阅后发布,以及先发布后订阅
var Event = (function() {
var clientList = {},
pub,
sub,
remove;
var cached = {};
sub = function(key, fn) {
if (!clientList[key]) {
clientList[key] = [];
}
// 使用缓存执行的订阅不用多次调用执行
cached[key + "time"] == undefined ? clientList[key].push(fn) : "";
if (cached[key] instanceof Array && cached[key].length > 0) {
//说明有缓存的 可以执行
fn.apply(null, cached[key]);
cached[key + "time"] = 1;
}
};
pub = function() {
var key = Array.prototype.shift.call(arguments),
fns = clientList[key];
if (!fns || fns.length === 0) {
//初始默认缓存
cached[key] = Array.prototype.slice.call(arguments, 0);
return false;
}
for (var i = 0, fn; (fn = fns[i++]); ) {
// 再次发布更新缓存中的 data 参数
cached[key + "time"] != undefined
? (cached[key] = Array.prototype.slice.call(arguments, 0))
: "";
fn.apply(this, arguments);
}
};
remove = function(key, fn) {
var fns = clientList[key];
// 缓存订阅一并删除
var cachedFn = cached[key];
if (!fns && !cachedFn) {
return false;
}
if (!fn) {
fns && (fns.length = 0);
cachedFn && (cachedFn.length = 0);
} else {
if (cachedFn) {
for (var m = cachedFn.length - 1; m >= 0; m--) {
var _fn_temp = cachedFn[m];
if (_fn_temp === fn) {
cachedFn.splice(m, 1);
}
}
}
for (var n = fns.length - 1; n >= 0; n--) {
var _fn = fns[n];
if (_fn === fn) {
fns.splice(n, 1);
}
}
}
};
return {
pub: pub,
sub: sub,
remove: remove
};
})();
// app.js
App({
onLaunch: function(e) {
// 注册 storage,这是第二条
wx.Storage = Storage;
// 注册发布订阅模式
wx.yue = Event;
}
});
实际应用
// 添加收货地址页面订阅
onLoad: function (options) {
wx.yue.sub("addAddress", function (data) {
y.setData({
addAddress: data
})
})
}
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
// 取消多余的事件订阅
wx.Storage.removeItem("addAddress");
},
onUnload: function () {
// 取消多余的事件订阅
wx.yue.remove("addAddress");
}
// 传递地址页面获取好数据传递
wx.yue.pub("addAddress", data.info);
// 补充跳转返回
注意:使用完成数据后要注意卸载,在页面被关闭时操作
Storage
const Storage = {
setItem: function(key, obj, callback) {
wx.setStorage({
key: key,
data: obj,
success: callback || function() {}
});
},
getItem: function(key) {
return wx.getStorageSync(key);
},
removeItem: function(key) {
wx.removeStorage({
key: key
});
}
};
async await
使用runtime.js,使小程序支持 async await,拷贝文件至项目目录下。
const regeneratorRuntime = require("../../utils/runtime.js");
Page({
shopCartInit() {
var y = this;
// 拿到商铺位置信息再去渲染购物计算当前的address符合不符合规定
var showCartList = function() {
// 显示全局的地址信息
var globalAddress = wx.Storage.getItem("globalAddress");
if (globalAddress) {
y.setData({
globalAddress: globalAddress,
addr_id: globalAddress.id
});
y.calculateDistance(
qqmapsdk,
globalAddress.latitude,
globalAddress.longitude
);
} else {
y.setData({
globalAddress: {}
});
}
};
// await 等待获取商铺位置信息
async function getShopPosTionMsg() {
await util.promiseRequest(api.merchant_addr, {}).then(res => {
var data = res.data.response_data.lists[0];
y.setData({
shop_lat: data.latitude, // 商铺纬度
shop_lng: data.longitude, // 商铺经度
peiSongFanWei: data.scope // 配送范围
});
});
}
async function initData() {
await getShopPosTionMsg();
await showCartList();
util.closeLoading();
y.setData({
loading: false
});
}
// 开始执行
initData();
}
});
promise
引入github上的一个库,wx.promise
// 演示 wxPromise 的能力
wx.showLoading({
title: '加载中',
mask: true
})
wx.pro.request({
url: 'https://cnodejs.org/api/v1/topics',
data: {},
method: 'GET',
header: {'content-type': 'application/json'}
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
}).finally(() => {
wx.hideLoading()
})