评论

「笔记」简单实现服务端动态控制原生小程序界面灰色模式开关

在遇到公祭日或其它特殊日子的时候,我们需要将我们的网站、小程序变成灰色(黑白)模式,本文介绍通过小程序使用数据预拉取来动态控制灰色模式开关的方案以及相关实现代码。本文并非最佳方案,仅供参考。

前言

在遇到公祭日或其它特殊日子的时候,我们需要将我们的网站、小程序变成灰色(黑白)模式,如果是在网页端比较简单,只需设置*、html最外层标签的样式设置filter: grayscale(100%)即可。但是在小程序中如果直接设置page的样式的话会导致小程序内使用flex失效,布局出现错位的情况。

如何解决错位问题?以及如何通过服务端动态控制灰色模式开关请看下文。

注:此方式无法控制非自定义导航栏颜色,如想要实现更完美的效果,请配合使用自定义导航栏。

原生小程序前端设置灰色模式:

wxml

<view class=“grayscale”>
<view class=“content”></view>
…小程序代码
</view>

wxss

.grayscale .content,
.grayscale text,
.grayscale button {
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
}

第三方UI组件/库(如:vant)

.grayscale .van-goods-action,
.grayscale .van-submit-bar,
.grayscale .van-swipe-cell {
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: grayscale(100%);
}

切忌直接设置

page {
filter: grayscale(100%);
}
小结:简单来说,就是把样式控制明确到具体的标签。

服务端动态控制

接下来讲我们利用小程序的数据预拉取来实现动态开关。

之所以选择使用数据预拉取来控制,是因为灰色模式并不是我们日常运营所需,如果单独封装到一个请求中去,会造成不必要的资源浪费,而且数据预拉取会在用户每次访问小程序的时候都会执行一次,所以能够保证尽可能实时获取到最新的状态,但是因为本身也是异步请求,所以无法100%保证页面加载完之前,就能够实时响应,所以返回的class并没有直接设置在全局变量globalData中,而是先存到本地存储Storage里,当我们在小程序后台关闭数据预拉取后,小程序端便不会再去请求相关接口,这样就做到了随时控制开关的效果了。

实现方式:

app.js

App({
onLaunch: async function (options) {
// 此处用于服务端鉴权,可根据自身情况设置
wx.setBackgroundFetchToken({
token: ‘grayscale’
})
wx.onBackgroundFetchData((res) => {
if(res.fetchedData && res.fetchedData.class) {
wx.setStorageSync(‘class’, res.fetchedData.class);
}
})
},
globalData: {
grayscale: wx.getStorageSync(“class”).grayscale || “”
}
})

需要灰色模式的wxml

<view class="{{grayscale}}">
<view class=“content”></view>
…小程序代码
</view>

需要灰色模式的js

const app = getApp()
Page({
data: {
grayscale: app.globalData.class.grayscale
}
})

服务端(node.js)接收到微信推送的get请求后返回数据

ctx.body = {
class: {
grayscale: “grayscale”
}
}

PS:以上方案仅供参考,当前方案在微信开发者工具中因缓存问题无法实时控制,iOS端基本上是没什么大问题,如果其它更好的方案可自行处理。

最后一次编辑于  2022-12-03  
点赞 6
收藏
评论

2 个评论

  • A notorious liar(小花猫)
    A notorious liar(小花猫)
    2022-12-06

    page::before{

    content: "";

    width: 100vw;

    height: 100vh;

    position: fixed;

    inset: 0;

    backdrop-filter: grayscale(100%);

    pointer-events: none;

    z-index: 99999999999999;

    }


    如果是自定义的tabbar 也可以完全遮住 如果不是tabbar那边需要自己再处理一下


    2022-12-06
    赞同
    回复
  • 风子
    风子
    2022-12-02

    借鉴了

    2022-12-02
    赞同
    回复
登录 后发表内容