[Front-end basics] Functional arrangement

insert image description here
insert image description here

Coordinate system transformation

The browser's default coordinate system is based on the upper left corner as the origin, the right as the origin x轴, and the downward as the origin y轴.
This coordinate system does not match the coordinate system used in mathematics. In order to more conveniently use functions to describe the layout of the page, it needs to be used cssto transform the browser's coordinate system.
The following css customizes --xand --ytwo custom properties, and clacrealizes a coordinate system with the center as the origin, the x-axis to the right, and the y-axis to the up through dynamic calculation. Coordinates are specified by --xand two attributes.--y
insert image description here

li {
    
    
  --dx: 0px;
  --dy: 0px;
  position: absolute;
  top: calc(50% - var(--dy));
  left: calc(50% + var(--dx));
}

Curve

A curve class is defined below, which receives three parameters for initialization, which are:

  • function describing the curve
  • x-axis value range
  • y-axis value range

A function is also provided getYto return the corresponding y value according to the value of x, and make certain processing if it exceeds the range.

class Curve {
    
    
  constructor(curveFunc, xRange, yRange) {
    
    
    this.curveFunc = curveFunc;
    this.xRange = xRange;
    this.yRange = yRange;
  }

  getY(x) {
    
    
    let y = this.curveFunc(x);
    if(x < this.xRange[0]) {
    
    
      y = this.curveFunc(this.xRange[0]);
    } else if (x > this.xRange[1]) {
    
    
      y = this.curveFunc(this.xRange[1]);
    }

    if(y < this.yRange[0]) {
    
    
      y = this.yRange[0];
    } else if(y > this.yRange[1]) {
    
    
      y = this.yRange[1];
    }

    return y;
  } 
}

layout function

function description

The layout function lays out the DOM elements according to the curve class defined above.
This function receives 4 parameters.

  • curve object
  • array of elements to lay out
  • The width occupied by the layout
  • height occupied by the layout

Implementation ideas

  1. The function first obtains the boundary points of the function domain and value domain according to the curve.
  2. The position of the center point is calculated from the needle boundary points.
  3. Then calculate the scaling ratio based on the width and height occupied by the layout.
  4. The stride (space between elements) is calculated based on the domain extent and the number of layout elements.
  5. Iterate through each element, and set the coordinates of each element calculated according to the step size and scaling.
function layout(curve, doms, width, height) {
    
    
  const [xmin, xmax] = curve.xRange;
  const [ymin, ymax] = curve.yRange;

  const cx = (xmin + xmax) / 2;
  const cy = (ymin + ymax) / 2;

  const scaleX = width / (xmax - xmin);
  const scaleY = height / (ymin - ymax);

  const step = (xmax - xmin) / doms.length;
  for(let i = 0; i < doms.length; i++) {
    
    
    const dom = doms[i];
    const x = xmin + i * step;
    const y = curve.getY(x);

    const dx = (x - cx) * scaleX;
    const dy = (y - cy) * scaleY;

    dom.style.setProperty('--dx', dx + 'px');
    dom.style.setProperty('--dy', dy + 'px');
  }
}

layouts mapping

Create different curve objects according to the layout requirements, and use the layout function to layout them.

const layouts = {
    
    
  wave() {
    
    
    const wave = new Curve(x => Math.sin(x), [0, Math.PI * 3], [-1, 1]);
    layout(wave, doms, container.clientWidth - 100, container.clientHeight / 2);
  },
  line() {
    
    
    const line = new Curve(x => 1, [0, 1], [0, 2]);
    layout(line, doms, container.clientWidth - 100, container.clientHeight / 2);
  },
  corssLine() {
    
    
    const curve1 = new Curve(x => x, [-1,1], [-1,1]);
    const curve2 = new Curve(x => -x, [-1, 1], [-1, 1]);
    const midIndex = Math.floor(doms.length / 2);
    const doms1 = Array.from(doms).slice(0, midIndex);
    const doms2 = Array.from(doms).slice(midIndex);
    layout(curve1, doms1, container.clientWidth - 100, container.clientHeight / 2);
    layout(curve2, doms2, container.clientWidth - 100, container.clientHeight / 2);
  },
  corssWave() {
    
    
    const curve1 = new Curve(x => Math.sin(x), [0, Math.PI * 3], [-1,1]);
    const curve2 = new Curve(x => -Math.sin(x), [0, Math.PI * 3], [-1, 1]);
    const midIndex = Math.floor(doms.length / 2);
    const doms1 = Array.from(doms).slice(0, midIndex);
    const doms2 = Array.from(doms).slice(midIndex);
    layout(curve1, doms1, container.clientWidth - 100, container.clientHeight / 3);
    layout(curve2, doms2, container.clientWidth - 100, container.clientHeight / 3);
  }
}

Finally, traverse the buttons to realize the binding of events, and different buttons correspond to different layouts.

const btns = document.querySelectorAll('button');

const events = Object.values(layouts);
btns.forEach((item, index) => {
    
    
  item.addEventListener('click', events[index]);
})

Guess you like

Origin blog.csdn.net/m0_66711291/article/details/131819277