Recently, my boss arranged a task to make a data visualization page and display it on the large data screen in the company’s exhibition hall. UI threw me a 3000 * 1672 design draft in a minute after determining the size of the large screen.

Screen adaptation Problem

In order to meet the normal display of the large screen in the exhibition hall, the page must be written in strict accordance with the size of the design draft. However, this fixed size writing method will have obvious screen adaptation problems, in the small size of the computer screen or larger size of the large screen will appear scroll bar or occupy the screen.

Principle of Screen adaptation

It is simply not practical for the UI to give us different sizes for different screens. The only way to do this is to make our pages like images that can be scaled to fit different containers.

Lock the screen aspect ratio

We need to get it all on one screen. This requires that the content of the page be wide and high enough to zoom freely to fill the entire screen like an image. This way of filling the entire screen can be interpreted as locking the aspect ratio of the screen. That is, regardless of the size of the design, the width and height of the content displayed on different screens should be consistent with the screen size. This scheme works perfectly on a large screen, but there is some distortion on a screen that does not match the aspect ratio of the design draft.

To allow content to be displayed on one screen on any screen, locking the aspect ratio of the screen would be ideal. If the boss is still obsessing over subtle transformations on the computer screen, I’ll be on the run all night. O (╥ man ╥) o

Realize the principle of

The implementation of scaling content is very simple, we put the written content in the top container component, and then scale the container component.

<! <bi-container class="bi-container" ref="biContainer"> <div> </bi-container>Copy the code

Lock screen draft aspect ratio implementation

// Let width = XXX // Let height = XXX // Let screenWidth = XXXX // screen viewport width let ScreenHeight = XXXX // Screen viewport height // Calculate the zoom ratio let widthScaleRadio = screenWidth/originalWidth let heightScaleRadio = ScreenHeight originalHeight / / zoom enclosing the content $refs. BiContainer. Style. Transform = ` scale (${widthScaleRadio}. ${heightScaleRadio })`Copy the code

Here’s the thing. When we scale an element, its default base point is in the center. We need to set the base point to the upper left corner of the element and have it fixed to the upper left corner of the screen.

.bi-container{
	position: fixed;
	top: 0;
	left: 0;
	z-index: 999;
	transform-origin: left top;
}
Copy the code

Container component development

The data large screen container component has two main functions

  • During initialization, the width and height are zoomed in and out to lock the width and height ratio of the screen to display all contents on one screen
  • Listen for the resize event. When the user scales the browser window to change the viewport size, rescale the content, lock the screen aspect ratio, and keep the entire content displayed on one screen.

For full implementation of container components, please click here: Data Large screen Container component Repository

Some core code is attached below:

<! <bi-container :options="{width: 3000, height: 1672}"> <! <img class="content" SRC ="... /assets/1.jpeg" alt="" /> </bi-container>Copy the code
Data () {return {width: 0, // width: 0, // width: 0, // width: 0, // width: 0, // width: 0, // window: 0, // window: 0,}; },Copy the code
Async Mounted () {// Get await this.initsize (); This.updatesize (); // Set the container size to match the content size this.updatesize (); This.updatescale (); // Set the container scale to display the contents in one screen. AddEventListener ('resize', this.onresize); }, beforeDestroy () {/ / window. The page destroyed before removing the resize event listeners removeEventListener (' resize, enclosing onResize); },Copy the code
InitSize () {return new Promise(resolve => {this.$nextTick(() => {// Get the actual size of the large screen if (this.options.width && this.options.height) { this.width = this.options.width; this.height = this.options.height; } else {if not deliver time the true size, / /, obtain the size of the container is content after all As this time the real size. Width = this. $refs. BiContainer. ClientWidth; this.height = this.$refs.biContainer.clientHeight; } // Get the original window size if (! this.originalWidth || ! this.originalHeight) { this.originalWidth = window.screen.width; this.originalHeight = window.screen.height; }}); resolve(); }); },Copy the code
// Set the container size, Let the container size and content size consistent updateSize () {if (this. Width && enclosing height) {this. $refs. BiContainer. Style. The width = ` ${this. Width} px `; this.$refs.biContainer.style.height = `${this.height}px`; }},Copy the code
UpdateScale () {// If the screen viewport exists, the real viewport is changed due to zooming and dragging. Here for real the viewport size of const currentWidth = document. Body. ClientWidth; const currentHeight = document.body.clientHeight; / / ultimately wide screen is high, if do not have large screen size, will screen viewport as original size bigger eventually high const wide realWidth = this. Width | | this. OriginalWidth. const realHeight = this.height || this.originalHeight; Const widthScale = currentWidth/realWidth; const heightScale = currentHeight / realHeight; this.$refs.biContainer.style.transform = `scale(${widthScale}, ${heightScale})`; },Copy the code
Async onResize() {await this.initsize (); async onResize() {await this.initsize (); this.updateScale(); }Copy the code

The final result