Mixed development problem

authorcontenttime
JJMixed development problem20220117

Style adaptation problem


The same page and the same element show the two patterns on the left and right (the resolution of Huawei mate30pro is 1176 * 2400, and the width unit is rem).

Let's think about it. Why is there this problem?

Extend it

Pixel classification: device pixels and CSS pixels

  1. Device independent pixels: the physical pixels of the device screen. The number of physical pixels of any device is fixed
  2. CSS pixels: also known as logical pixels, it is an abstract layer created for web developers and used in CSS and javascript
  3. Every CSS declaration and almost all javascript attributes use CSS pixels, so device pixels are never actually used.

On the desktop side, a pixel of css often corresponds to a physical pixel of the computer screen.


On the mobile phone, due to the limitation of screen size, zooming is a frequent operation.

When zooming out, one device pixel covers multiple CSS pixels

When zooming in, one CSS pixel covers multiple device pixels

The CSS pixels (such as width:300px) set by the element are always the same regardless of reduction or enlargement, and the number of device pixels corresponding to a CSS pixel is determined according to the current zoom scale.

We have to mention the viewport in HTML. We often set the width of the viewport = device width. What is the value of the device width?

<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"/>  

Device width = 320 for iPhone 5, 375 for iPhone 6 and 414 for iPhone 6 +.

DPR:

	Device pixel ratio DPR(devicePixelRatio)Yes, the default zoom is 100%In the case of device pixels and CSS Pixel ratio

dpr, also known as device pixel ratio, is the ratio of physical pixels to logical pixels, which is not difficult to understand: dpr=2 under iPhone 6 and dpr=3 under iPhone 6 + (considering the pixels in rasterization, not real physical pixels;

Cause of problem:

Due to the Huawei browser version problem, the minimum pixel supported by the low version of Huawei browser is 12px, while the high version is unlimited.

How to avoid similar problems:

Postcss pxtorem and flexible
Postcss pxtorem function: convert px to rem
flexible function: calculate the root font size( flexible.js )

Usage of postcss pxtorem:

main.js

// flexible is introduced to set the benchmark value of rem
import 'lib-flexible/flexible.js';

.postcssrc.js configuration

module.exports = {
  "plugins": {
    "postcss-import": {},
    "postcss-url": {},
    // to edit target browsers: use "browserslist" field in package.json
    "autoprefixer": {},
    'postcss-pxtorem': {
      rootValue({ file }) {
        return file.indexOf('vant') !== -1 ? 37.5 : 117.6;(width/10)
      },
      "propList": ['*'],
    "selectorBlackList": ['.norem']  // Filter it out Classes beginning with norem are not converted
    }
  }
}

1px border (vant)

<!-- border-top  --> 
<div class="van-hairline--top"></div>

Mobile 1px implementation scheme( https://zhuanlan.zhihu.com/p/100752129 )

performance optimization

Route lazy loading

1, Definition

Lazy loading simply means delayed loading or on-demand loading, that is, loading when needed.

2, Writing method

There are two common lazy loading methods: using vue asynchronous components and import ing in ES

Unloaded writing method: import index from '@/pages/index/index.vue';
Lazy loading method 1: const index = () => import('@/pages/index/index.vue');
	routes: [
    {
      path: '/',
      name: 'index',
	  component: index
	}]
Lazy loading method 2
	routes: [
    {
      path: '/',
      name: 'index',
      component: resolve=>(require(["@/pages/index/index.vue"],resolve))
    }]

3, Difference after packaging

The js folder in dist package was not loaded lazily

Modify to lazy load js folder in dist package

Picture compression( https://tinypng.com/ )

Open gzip

1, Disposition

config/index.js/productionGzip: true (the packaging effect is shown in the figure above)

2, Effect



When the HTML document is parsed, DOMContentLoaded will be triggered, and the load event will not be triggered until all resources are loaded. The $(document) often used in jQuery Ready (function() {/ /... Code...}); In fact, the DOMContentLoaded event is monitored, and $(document) Load (function() {/ /... Code...}); The load event is monitored.

3, Using Android shell cdr cache


Components load on demand

1, vant load on demand

2, Ecarts load on demand


main.js

Use cdn cache (network restrictions not used)

1, Resource introduction

In index HTML, add CDN resources, such as those on bootstrap:

 <body>
	<div id="app"></div>
	<script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
	<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
</body>

2, Add configuration

In bulid / webpack base. Add externals in conf.js file to import the referenced external module, as follows:

module.exports = {
	entry: {app: './src/main.js'},
	externals:{'vue': 'Vue','vue-router': 'VueRouter'}
}

3, Remove the original reference

Remove import and Vue Use (xxx), etc

// import Vue from 'vue'
// import Router from 'vue-router'
// Vue.use(Router)

Interactive optimization

1, Increase timeout

ajax.js,

ajax.defaults.timeout = 10000;

2, Add timeout prompt

ajax.js post interceptor error, added

	if (error && error.stack.indexOf('timeout') > -1) {
       		Toast.fail({message: 'The connection timed out. Please check your network'});} 
		else if (error && error.stack.indexOf('Network Error') > -1) {        
			Toast.fail({ message: 'The current network is unavailable. Please check your network'});    
	}

Weixin JS SDK usage

npm i -S weixin-js-sdk

use

//introduce
import wx from 'weixin-js-sdk';
//Request interface to get jsapi_ticket
const params = {
    //Current page url
    url:location.href.split('#')[0],
    //Random string
    noncestr:Math.random().toString(36)
    .substr(2, 15),
    //time stamp
    timestamp:parseInt(new Date().getTime() / 1000)
};
//Register after the interface returns the bill
   wx.config({
       debug: false,
       appId: 'wld341060039',
       timestamp:params.timestamp,
       nonceStr: params.noncestr,
       signature: res.ticket,
       //Register events select photos / take photos to get local photo data
       jsApiList: ['chooseImage', 'getLocalImgData']
   	});
    // Successful verification is processed through the ready interface
    wx.ready(function () {
        console.log(666);
    });
    // Failed to process validation through the error interface
    wx.error(function (res) {
        console.log('error', res);
    });
    // Judge whether the current client version supports the specified JS interface
    wx.checkJsApi({
        // List of JS interfaces to be tested. See Appendix 2 for the list of all JS interfaces,
        jsApiList: ['chooseImage', 'getLocalImgData'],
        success: function (res) {
            console.log(res);
            // It is returned as a key value pair. The available api value is true and the unavailable api value is false
            // For example: {"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
        }
	});

Take a picture or select a picture interface from your phone's photo album

wx.chooseImage({
    count: 1, // Default 9
    sizeType: ['original', 'compressed'], // You can specify whether to use the original or compressed image. Both are available by default
    sourceType: ['album', 'camera'], // You can specify whether the source is an album or a camera. Both are available by default
    quality: 0.8, //The compression quality ranges from 0 to 1. The smaller the value, the lower the quality and the higher the compression rate (only valid for jpg)
    success: function (res) {
    	// Returns the local ID list (absolute path) of the selected photo. The local ID can be used as the src attribute of the img tag to display the picture
   		 var localIds = res.localIds; 
    }
});

Get local picture interface

wx.getLocalImgData({
    localId: '', // localID of the picture
    success: function (res) {
    //localData is the base64 data of the picture, which can be displayed with the img tag
    let localData = res.localData;
    //ios compatibility with Android
    if (localData.indexOf('data:image') != 0) {
        // Determine whether there is such a head
        localData = `data:image/jpeg;base64,${localData}`;
        }
        localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg'); 
    }
});

ios compressed picture problem

Image compression method

 cutImageBase64(base64, w, callback) {
      const newImage = new Image();
      let quality = 0.6; // Compressibility between 0-1
      newImage.src = base64;
      newImage.setAttribute('crossOrigin', 'Anonymous'); // Required when the url is a foreign domain
      let imgWidth, imgHeight;
      newImage.onload = function () {
      imgWidth = this.width;
      imgHeight = this.height;
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      if (Math.max(imgWidth, imgHeight) > w) {
          if (imgWidth > imgHeight) {
                  canvas.width = w;
                  canvas.height = w * imgHeight / imgWidth;
              } else {
                  canvas.height = w;
                  canvas.width = w * imgWidth / imgHeight;
              }
          } else {
              canvas.width = imgWidth;
              canvas.height = imgHeight;
              quality = 0.6;
      }
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
      let base64 = canvas.toDataURL('image/jpeg', quality); // Compression statement
      // If you want to ensure that the picture is compressed to the size you want, if it is required to be between 50-150kb, please add the following statement. The initial value of quality is determined according to the situation
      while (base64.length / 1024 > 150) {
          quality -= 0.01;
          base64 = canvas.toDataURL('image/jpeg', quality);
      }
      // Prevent the last compression from falling below the minimum size, as long as the decrease in quality is reasonable, it does not need to be considered
      while (base64.length / 1024 < 50) {
          quality += 0.001;
          base64 = canvas.toDataURL('image/jpeg', quality);
      }
      	// It must be returned through the callback function, otherwise the value cannot be obtained in time
      	callback(base64);
      };
  }

Use compressed pictures

this.cutImageBase64(base64, 700, this.uploadImgbas);

Compressed data

uploadImgbas(base64) {	console.log(base64)}

ios considerations

In IOS, canvas drawing pictures has two limitations:
   the first is the size of the picture. If the size of the picture exceeds 2 million pixels, the picture cannot be drawn on the canvas. There will be no error when calling drawImage, but when you use toDataURL to obtain picture data, you get empty picture data.
  moreover, the size of the canvas is limited. If the size of the canvas is greater than about 5 million pixels (i.e. the width height product), not only the picture can not be drawn, but also anything else can not be drawn.
   in response to the above two restrictions, I control the image width and height compression within 1000px, so that the maximum image does not exceed 2 million pixels. In front-end development, 1000px*1000px can basically meet most of the needs. Of course, there is a more perfect tile drawing method. Let's say tile drawing method here.
  in this way, the two limitations on IOS are solved.

In addition to the above limitations, there are two pitfalls. One is that the toDataURL of canvas can only compress jpg. When the image uploaded by the user is png, it needs to be converted to JPG, that is, canvas toDataURL ('image/jpeg ', 0.5), the type is uniformly set to JPEG, and the compression ratio is controlled by itself.

The other is that if png is converted to JPG and there is a transparent area in the canvas when drawing on the canvas, the transparent area will turn black when converting to jpg. Because the transparent pixel of the canvas is rgba(0,0,0,0), it will become RGBA (0,0,1) when converting to JPG, that is, the transparent background will turn black. The solution is to lay a white background on the canvas before drawing.

Keywords: Javascript

Added by pete_bisby on Mon, 17 Jan 2022 10:45:23 +0200