面试题:React实现鼠标托转文字绕原点旋转,进阶加薪全靠它

22 阅读2分钟

margin: 0;

padding: 0;

}

.app{

width: 800px;

height: 800px;

/background-color: red;/

position: relative;

border: 1px solid #000;

}

.circle{

height: 6px;

width: 6px;

border-radius: 50%;

background-color: orange;

position: absolute;

left: 50%;

top: 50%;

transform: translate(-3px);

}

.text{

padding: 0;

margin: 0;

border: 1px solid #999999;

font-weight: bolder;

position: absolute;

display: flex;

justify-content: center;

align-items: center;

z-index: 999;

user-select: none;

}

.inside_circle{

height: 6px;

width: 6px;

border-radius: 50%;

background-color: #00ff18;

position: absolute;

cursor: pointer;

}

版本2.0

================================================================

运行效果:

================================================================

在这里插入图片描述

思路:改进了一些地方,通过两直线相交,将起点改为了与DIV的交点。同时终点距离黄色圆圈有一定距离。

============================================================================================================

方法:

  1. 两直线相交

  2. 相似

React代码:

===================================================================

App.js


import './App.css';

import React from 'react'

class App extends React.Component {

constructor(props) {

super(props);

this.circle = React.createRef();

this.state = {

left: 0,

top: 0,

moveFlag: false,

orangeX: 401,

orangeY: 404

}

}

componentDidMount() {

document.onmousemove = (e) => {

if (this.state.moveFlag) {

let {pageX, pageY} = e;

// 1. 更改矩形位置

if (this.state.moveFlag) {

this.setState({

left: pageX - 25,

top: pageY - 10

})

}

// 2. 清空画布并绘制新的线

this._cleanCanvas((ctx) => {

// 2.1 生成text和circle

const text = {

getBBox: () => {

return {

x: pageX,

y: pageY,

width: 50,

height: 20

}

}

}

const circle = {

center: {

x: 401,

y: 404

},

radius: 3

}

let res = this._around(text, circle)

this._drawNewLine(ctx, res);

// this._drawNewLine(ctx, pageX, pageY);

});

}

}

}

render() {

const {left, top} = this.state

return (

ref={this.circle}

style={{left, top}}

className='text'>RPL10

<span

onMouseDown={(e) => this._mouseDown(e)}

onMouseUp={(e) => this._mouseUp(e)}

className='inside_circle'

/>

);

}

_mouseDown(e) {

this.setState({

moveFlag: true

})

this.circle.current.style.left = 50

}

_mouseUp(e) {

if (this.state.moveFlag) {

this.setState({

moveFlag: false

})

}

}

_cleanCanvas(drawNewLine) {

// 清空画布

let canvas = document.querySelector('#canvas');

let ctx = canvas.getContext('2d');

canvas.height = 800;

drawNewLine && drawNewLine(ctx)

}

_drawNewLine(ctx, linePoint) {

ctx.moveTo(linePoint.startPt.x, linePoint.startPt.y);

// 4. 绘制直线

ctx.lineTo(linePoint.endPt.x, linePoint.endPt.y);

// 5. 描边

ctx.stroke();

}

_around(text, circle) {

const bBox = text.getBBox();

const centerBox = {

x: bBox.x,

y: bBox.y,

};

const centerCircle = {

x: circle.center.x,

y: circle.center.y

}

const radius = circle.radius;

const endPtDistCircle = 3;

let lineSeg = {

startPt: {

x: undefined,

y: undefined

},

endPt: {

x: undefined,

y: undefined

}

}

// 计算lineSeq

// 1. 获取正方形四个点,根据不同情况,判断四点交点,计算起始点

const leftTop = {

x: centerBox.x - bBox.width * 0.5,

y: centerBox.y - bBox.height * 0.5

};

const leftBottom = {

x: centerBox.x - bBox.width * 0.5,

y: centerBox.y + bBox.height * 0.5

};

const rightTop = {

x: centerBox.x + bBox.width * 0.5,

y: centerBox.y - bBox.height * 0.5

};

const rightBottom = {

x: centerBox.x + bBox.width * 0.5,

y: centerBox.y + bBox.height * 0.5

}

// 2. 计算终点

// 2.1 计算两个圆点之间的距离

let distance = this._distance(centerCircle, centerBox);

let diffX = 6 * (centerCircle.x - centerBox.x) / distance;

let diffY = 6 * (centerCircle.y - centerBox.y) / distance;

if (centerBox.x < centerCircle.x && centerBox.y < centerCircle.y) {

// 左上

lineSeg.startPt = this._interSectionPoint(leftBottom, rightBottom, centerBox, centerCircle) || this._interSectionPoint(rightTop, rightBottom, centerBox, centerCircle)

lineSeg.endPt = {

x: centerCircle.x - diffX,

y: centerCircle.y - diffY

}

} else if (centerBox.x < centerCircle.x && centerBox.y > centerCircle.y) {

// 左下

lineSeg.startPt = this._interSectionPoint(leftTop, rightTop, centerBox, centerCircle) || this._interSectionPoint(rightTop, rightBottom, centerBox, centerCircle)

lineSeg.endPt = {

x: centerCircle.x - diffX,

y: centerCircle.y - diffY

}

} else if (centerBox.x > centerCircle.x && centerBox.y < centerCircle.y) {

// 右上

lineSeg.startPt = this._interSectionPoint(leftTop, leftBottom, centerBox, centerCircle) || this._interSectionPoint(leftBottom, rightBottom, centerBox, centerCircle)

lineSeg.endPt = {

x: centerCircle.x - diffX,

y: centerCircle.y - diffY

}

} else if (centerBox.x > centerCircle.x && centerBox.y > centerCircle.y) {

// 右下

lineSeg.startPt = this._interSectionPoint(leftTop, rightTop, centerBox, centerCircle) || this._interSectionPoint(leftBottom, leftTop, centerBox, centerCircle)

lineSeg.endPt = {

x: centerCircle.x - diffX,

y: centerCircle.y - diffY

}

}

return lineSeg;

}

/**

  • 直线ab和直线cd的交点坐标

*/

_interSectionPoint(a, b, c, d) {

let denominator = (b.y - a.y) * (d.x - c.x) - (a.x - b.x) * (c.y - d.y);

if (denominator === 0) {

return false;

}

let x = ((b.x - a.x) * (d.x - c.x) * (c.y - a.y)

  • (b.y - a.y) * (d.x - c.x) * a.x
  • (d.y - c.y) * (b.x - a.x) * c.x) / denominator;

let y = -((b.y - a.y) * (d.y - c.y) * (c.x - a.x)

  • (b.x - a.x) * (d.y - c.y) * a.y
  • (d.x - c.x) * (b.y - a.y) * c.y) / denominator;

if (

(x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0

&& (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0

) {

// 返回交点p

return {

x: x,

y: y

}

}

//否则不相交

return false

}

/**

  • 求a、b两点之间的距离

  • @param a

  • @param b

*/

_distance(a, b) {

let dx = Math.abs(a.x - b.x);

let dy = Math.abs(a.y - b.y);

Vue

  • 什么是MVVM?

  • mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?

  • 组件之间的传值?

  • Vue 双向绑定原理

  • 描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?

  • 虚拟 DOM 实现原理

  • Vue 中 key 值的作用?

  • Vue 的生命周期

  • Vue 组件间通信有哪些方式?

  • vue 中怎么重置 data?

  • 组件中写 name 选项有什么作用?

  • Vue 的 nextTick 的原理是什么?

  • Vuex 有哪几种属性?

    开源分享:docs.qq.com/doc/DSmRnRG…