前端常用的一些代码段

文章目录

判断多个时间区间是否有交叉

// 基于moment
function iscover(dates){
	for (var i = 0; i < dates.length; i++) {
	    for (var j = 0; j < dates.length; j++) {
	        if (i != j) {
	            if (
	                moment(dates[j][0]).isBetween(dates[i][0], dates[i][1]) ||
	                moment(dates[j][0]).isSame(dates[i][0]) ||
	                moment(dates[j][0]).isSame(dates[i][1]) ||
	                moment(dates[j][1]).isBetween(dates[i][0], dates[i][1]) ||
	                moment(dates[j][1]).isSame(dates[i][0]) ||
	                moment(dates[j][1]).isSame(dates[i][1])
	            ) {
	                return { i:i, j:j };
	            }
	        }
	    }
	}
	return true;
}

var dateArr = [
	['2021-06-03','2021-06-05'],
	['2021-06-06','2021-06-08'],
	['2021-06-04','2021-06-05']
]
var c = iscover(dateArr)
if(c!==true){
	console.log(`${c.i}${c.j}交叉哦!`); // 0和2交叉哦!
}

A追逐B(点A向点B靠近)

// aim趋向cur,一般用来做鼠标跟随.
function lerpDistance(aim, cur, ratio) {
	var delta = cur - aim;
	return aim + delta * ratio;
}

document.addEventListener('mousemove',mouseMove)
var x = 350,y = 350;
function mouseMove(e) {
	if (e.offsetX || e.layerX) {
		var px = e.offsetX == undefined ? e.layerX : e.offsetX;
		var py = e.offsetY == undefined ? e.layerY : e.offsetY;
		if(px>=0 && px<=700&& py>=0 && py<=700) {
			x = lerpDistance(x, px, 0.3);
			y = lerpDistance(y, py, 0.3);
		}
	}
}

获取随机数区间

 function rangeRandom (m,n){
  return Math.floor(Math.random()*(m - n) + n);
}
// 获取100-600中间的随机数
console.log(rangeRandom(100, 600))

角度b趋向角度a

function lerpAngle(a, b, t) {
	var d = b - a;
	if (d > Math.PI) d = d - 2 * Math.PI;
	if (d < -Math.PI) d = d + 2 * Math.PI;
	return a + d * t;
}

document.addEventListener('mousemove',mouseMove)
var x = 350,y = 350,angle = 0;
function mouseMove(e) {
  if(e.layerX>=0 && e.layerX<=700&& e.layerY>=0 && e.layerY<=700) {
  	var _angle = Math.atan2(y-e.layerY ,x-e.layerX); // 计算(x,y)点到鼠标当前的点的角度
   	angle = lerpAngle( _angle, angle  , .3); // angle向_angle靠拢
  	rotate(angle); // 旋转这个角
  }
}

简单的碰撞检测

// 点(x1,y2)和点(x2,y2)之间的距离的平方
function calLength(x1, y1, x2, y2) {
	return Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2);
}
// 以点(1,1)为中心画了个圆圈,半径为2,以点(5,6)为中心画了个圆圈,半径为3
var len = calLength(1, 1, 5, 6); 
if(len <= (2+3) * (2+3)){ console.log('碰撞到一起啦!') }

el中是否包含classname

const hasClass = (el: Element, className: string) => el.classList.contains(className);

判断el上有没有className,有的话就移除,没有的话就添加上

const toggleClass = (el: Element, className: string) => el.classList.toggle(className); 

xpath获取单个element

const getElementByPath = (path: string) => return document.evaluate(path, document).iterateNext();

xPath获取element集合

  const getElementsByPath = (path: string) => {
    const result = document.evaluate(path, document, null, XPathResult.ANY_TYPE, null);
    const ret = [];
    let nodes = result.iterateNext();
    if (nodes) {
        ret.push(nodes)
    }
    while (nodes) {
        nodes = result.iterateNext();
        if (nodes) {
            ret.push(nodes)
        }
    }
    return ret;
  }

反向获取xPath路径

    function readXPath(element) {
      if (element.id !== "") {
        return '//*[@id="' + element.id + '"]';
      }
      if (element == document.body) {
        return "/html/" + element.tagName.toLowerCase();
      }
      let x = 1, siblings = element.parentNode.childNodes; //同级的子元素
      for (let i = 0, l = siblings.length; i < l; i++) {
        const sibling = siblings[i];
        if (sibling == element) {
          if (element.parentNode) {
            return readXPath(element.parentNode) + "/" + element.tagName.toLowerCase() + "[" + x + "]"  
          }
        } else if ( sibling.nodeType == 1 && sibling.tagName == element.tagName ) {
          x++;
        }
      }
    }

父节点parent中是否存在子节点 child

const inNode = (child: Element, parent: Element) => parent !== child && parent.contains(child);

隐藏element

const hideEl = (...el) => [...el].forEach(e => (e.style.display = 'none'));
hideEl(document.querySelectorAll('span'));

获取一个元素内的所有图像

const getImages = (el, includeDuplicates = false) => {
  const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
  return includeDuplicates ? images : [...new Set(images)];
};
getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...']
getImages(document, false); // ['image1.jpg', 'image2.png', '...']

添加一个元素的事件侦听器

const addEvent = (el, eventType, fn) => el.addEventListener(eventType, fn)

移除一个元素的事件侦听器

const removeEvent = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);

const fn = () => console.log('!');
addEvent(document.getElementById('box'), 'left', fn)
removeEvent(document.getElementById('box'), 'left', fn);

在给定元素上触发特定事件,且可选传递自定义数据

const triggerEvent = (el, eventType, detail) => el.dispatchEvent(new CustomEvent(eventType, { detail }));

//document.getElementById('box').addEventListener('left', (e) => {});
triggerEvent(document.getElementById('box'), 'left');
triggerEvent(document.getElementById('box'), 'left', { arg: 'hehe' });

确认指定元素是否在视口可见

const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
  const { top, left, bottom, right } = el.getBoundingClientRect();
  const { innerHeight, innerWidth } = window;
  return partiallyVisible
    ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
        ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
    : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};
elementIsVisibleInViewport(el); // (不完全可见)
elementIsVisibleInViewport(el, true); // (部分可见)

获取当前页面的滚动位置

const getScroll = (el = window) => ({
  x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
  y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});

平滑滚动到页面顶部

const animateScrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(animateScrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};

平滑的滚动到指定位置

调用:
// 滚动Y方向滚动条高度到5000
scrollToDistance(document.documentElement && document.documentElement.scrollLeft,5000);
// 滚动X方向滚动条高度到0
scrollToDistance(0,document.documentElement && document.documentElement.scrollTop);

// X,Y同时滚动
scrollToDistance(300,800)

function scrollToDistance(toXDistance, toYDistance) {
  let disX = toXDistance - Number(document.documentElement && document.documentElement.scrollLeft);
  let disY = toYDistance - Number(document.documentElement && document.documentElement.scrollTop);
  animateScrollToTop()
  function animateScrollToTop() {

    disX = Math.abs(disX) > 1 ? disX - disX / 8 : 1;
    disY = Math.abs(disY) > 1 ? disY - disY / 8 : 1;

    const retX = toXDistance - disX
    const retY = toYDistance - disY

    if (Math.abs(disX) > 1 || Math.abs(disY) > 1) {
      window.requestAnimationFrame(animateScrollToTop);
      window.scrollTo(retX, retY);
    }
  }
}

获取浏览器的 URL

window.location.href;  // 'https://baidu.com'

创建一个包含当前 URL 参数的对象

const getURLParameters = url =>
  (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
    (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
    {}
  );

getURLParameters('http://fanjiaxing.com/home?a=age&s=sex'); // {a: 'age', s: 'sex'}
getURLParameters('baidu.com'); // {}

对传递的 URL 进行 GET 请求

const httpGet = (url, callback, err = console.error) => {
  const request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.onload = () => callback(request.responseText);
  request.onerror = () => err(request);
  request.send();
};
httpGet(
  'https://jsonplaceholder.typicode.com/posts/1',
  console.log
); 
// Logs: {"userId": 1, "id": 1, "title": "sample title", "body": "my text"}

对传递的 URL 进行 POST 请求

const httpPost = (url, data, callback, err = console.error) => {
  const request = new XMLHttpRequest();
  request.open('POST', url, true);
  request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
  request.onload = () => callback(request.responseText);
  request.onerror = () => err(request);
  request.send(data);
};
const newPost = {
  userId: 1,
  id: 1337,
  title: 'Foo',
  body: 'bar bar bar'
};
const data = JSON.stringify(newPost);
httpPost(
  'https://jsonplaceholder.typicode.com/posts',
  data,
  console.log
); 
// Logs: {"userId": 1, "id": 1337, "title": "Foo", "body": "bar bar bar"}

分辨设备是移动设备还是桌面设备

const detectDeviceType = () =>
  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
    ? 'Mobile'
    : 'Desktop';

detectDeviceType(); // "Mobile" or "Desktop"

获取两个日期之间的天数间隔

const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
  (dateFinal - dateInitial) / (1000 * 3600 * 24);

getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9

将一组表单元素编码为一个对象

const formToObject = form =>
  Array.from(new FormData(form)).reduce(
    (acc, [key, value]) => ({
      ...acc,
      [key]: value
    }),
    {}
  );

formToObject(document.querySelector('#form')); // { email: 'test@email.com', name: 'Test Name' }

从对象中检索给定选择器指示的一组属性

const get = (from, ...selectors) =>
  [...selectors].map(s =>
    s
      .replace(/\[([^\[\]]*)\]/g, '.$1.')
      .split('.')
      .filter(t => t !== '')
      .reduce((prev, cur) => prev && prev[cur], from)
  );
const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] };

get(obj, 'selector.to.val', 'target[0]', 'target[2].a'); // ['val to select', 1, 'test']

在等待一定时间后调用提供的函数(单位毫秒)

const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
delay(
  function(text) {
    console.log(text);
  },
  1000,
  'later'
); 
// 一秒后记录 'later' 。

获得给定毫秒数的可读格式

const formatDuration = ms => {
  if (ms < 0) ms = -ms;
  const time = {
    day: Math.floor(ms / 86400000),
    hour: Math.floor(ms / 3600000) % 24,
    minute: Math.floor(ms / 60000) % 60,
    second: Math.floor(ms / 1000) % 60,
    millisecond: Math.floor(ms) % 1000
  };
  return Object.entries(time)
    .filter(val => val[1] !== 0)
    .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
    .join(', ');
};

formatDuration(1001); // '1 second, 1 millisecond'
formatDuration(34325055574); // '397 days, 6 hours, 44 minutes, 15 seconds, 574 milliseconds'

为指定选择器创建具有指定范围、步长和持续时间的计时器

const counter = (selector, start, end, step = 1, duration = 2000) => {
  let current = start,
    _step = (end - start) * step < 0 ? -step : step,
    timer = setInterval(() => {
      current += _step;
      document.querySelector(selector).innerHTML = current;
      if (current >= end) document.querySelector(selector).innerHTML = end;
      if (current >= end) clearInterval(timer);
    }, Math.abs(Math.floor(duration / (end - start))));
  return timer;
};

counter('#my-id', 1, 1000, 5, 2000); // 为 id="my-id" 的元素创建一个两秒的计时器

将一个字符串复制到剪贴板

const copyToClipboard = str => {
  const el = document.createElement('textarea');
  el.value = str;
  el.setAttribute('readonly', '');
  el.style.position = 'absolute';
  el.style.left = '-9999px';
  document.body.appendChild(el);
  const selected =
    document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
  if (selected) {
    document.getSelection().removeAllRanges();
    document.getSelection().addRange(selected);
  }
};

copyToClipboard('Lorem ipsum'); // 'Lorem ipsum' copied to clipboard.

确定页面的浏览器选项卡是否处于前台活跃状态

const isBrowserTabFocused = () => !document.hidden;

isBrowserTabFocused(); // true

当其选项卡的内容变得可见或被隐藏

function fn(){
	console.log('哎呀,你刚才是不是按了手机物理键退出啦!')
}
window.addEventListener('visibilitychange', fn);
window.removeEventListener('visibilitychange', fn);

数组里面对象去重

let newobj = {}; 
arr = arr .reduce((preVal, curVal) => {
	newobj[curVal.id] ? '' : newobj[curVal.id] = preVal.push(curVal); 
	return preVal 
}, [])

将tree深层嵌套结构的数据,重新组织或者拉平

export class FileNode {
  treeChildren: FileNode[];
  treeFilename: string;
  treeType: any;
  [key: string]: any;
}
 
export class FileFlatNode {
  [key: string]: any;
  constructor(
    public treeExpandable: boolean, 
    public treeFilename: string, 
    public treeLevel: number, 
    public treeType: any 
  ) {
  }
}
 
// 将数据重新组织成一个嵌套的tree
export const buildFileTree = (arr: any[]): FileNode[] => {
  return arr.reduce((pre, cur, index, arr) => {
    const node = new FileNode();
    node.treeFilename = cur.Name;
    for (const key in cur) {
      if (key !== 'ChildNode') {
        node[key] = cur[key];
      }
    }
    if (cur.ChildNode && cur.ChildNode.length) {
      node.treeChildren = buildFileTree(cur.ChildNode);
    }
    return pre.concat(node); // 将node合并到上一个pre数组中
  }, []); // pre 的初始值为[]
};
 
// 将数据重新组织,将子节点取出来放在和父节点平衡的数组里面,拉平成一个不嵌套的tree
export const buildFileFlatTree = (arr: any[], level: number, type: any = null): FileFlatNode[] => {
  return arr.reduce((pre, cur, index, arr) => {
 
    const node = new FileFlatNode(!!cur.ChildNode, cur.name, level, type);
	node.treeLevel = level;
    for (const key in cur) {
      if (key !== 'ChildNode') {
        node[key] = cur[key];
      }
    }
    let _pre = pre.concat(node);
    if (cur.ChildNode && cur.ChildNode.length) {
      _pre = _pre.concat(buildFileFlatTree(cur.ChildNode, level + 1, cur.name));
    }
    return _pre;
  }, []);
};

拼接树目录结构,添加层级索引

function deepDeptree(data, pac) {
    var str = '<div class="root">'
    var pac = pac || 0
    for (var i = 0; i < data.length; i++) {
        str += '<div sy=' + pac+ ' style="padding-left:' + (pac* 15)+'px">' + data[i].Name + ',' + pac+'</div>';
        if (data[i].ChildNode) {
            pac= pac + 1;
            str += deepDeptree(data[i].ChildNode, pac)
            pac--;
        }
    }
    str += '</div>'
    return str;
}

var str = deepDeptree(data)

根据子元素的guid获取所有父级的guid

// 逆序,获取当前部门的所有父元素的guid
function getParentsId(arr, PK_Guid) {
    var idArr = [];
    var fns = function(arr){
        for (const item of arr) {
            if (item.PK_Guid == PK_Guid) {
                idArr.push(item.PK_Guid);
                break;
            }
            if (item.ChildNode) {
                if (JSON.stringify(item.ChildNode).match(PK_Guid)) {
                    idArr.push(item.PK_Guid);
                }
                fns(item.ChildNode);
            }     
        }
    }
    fns(arr)
    return idArr;
}

// 获取当前部门的所有父元素的Name
function treeFindPath(tree, func, path) {
    path = path || [];
    if (!tree) return []
    for (var data of tree) {
        //这里按照你的需求来存放最后返回的内容吧
        path.push(data.Name)
        if (func(data)) return path
        if (data.ChildNode) {
            var findChildren = treeFindPath(data.ChildNode, func, path)
            if (findChildren.length) return findChildren
        }
        path.pop()
    }
    return []
}
treeFindPath(treeArr, function (data) { return data.PK_Guid == '12345678' })

根据id获取当前架构信息以及下级信息

function getOneInfo(data,id){
	let obj = null;
	function fn(data,id){
		for(const item of data){
			if(item.PK_Guid === id){
				obj = item;
				break;
			}
			if(item.ChildNode&&item.ChildNode.length){
				fn(item.ChildNode,id)
			}
		}
	}
	fn(data,id);
	return obj;
}

get set

 function City() {
 	this._open= false; 
 }

Object.defineProperty(City.prototype, "open", {
    get: function () { return this._open; },
    set: function (val) {
        this._open = val;
    },
    enumerable: true,
    configurable: true
});

http-server搭建本地服务器

1. npm install http-server -g
2. 进入目录,运行http-server即可

编辑serialize()

// 转成json数据;
 var data = getURLParameters(unescape(decodeURI($("#form").serialize()))) || {} 

css小箭头

<div id="test"></div>
#test{
  position: relative;
}
#test:after {
  border: 10px solid transparent;
  border-left: 10px solid #f00;
  width: 0;
  height: 0;
  position: absolute;
  content: ' '
}

//clip-path: polygon(27% 0, 92% 0, 6% 89%, 0% 100%); 也可以画箭头

获取ie浏览器版本

// 获取IE版本
export const  IEVersion = () => {
  // 取得浏览器的userAgent字符串
  const  userAgent = navigator.userAgent;
  // 判断是否为小于IE11的浏览器
  const  isLessIE11 = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1;
  // 判断是否为IE的Edge浏览器
  const  isEdge = userAgent.indexOf('Edge') > -1 && !isLessIE11;
  // 判断是否为IE11浏览器
  const  isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1;
  if (isLessIE11) {
      const  IEReg = new RegExp('MSIE (\\d+\\.\\d+);');
      // 正则表达式匹配浏览器的userAgent字符串中MSIE后的数字部分,,这一步不可省略!!!
      IEReg.test(userAgent);
      // 取正则表达式中第一个小括号里匹配到的值
      const  IEVersionNum = parseFloat(RegExp['$1']);
      if (IEVersionNum === 7) {
          // IE7
          return 7
      } else if (IEVersionNum === 8) {
          // IE8
          return 8
      } else if (IEVersionNum === 9) {
          // IE9
          return 9
      } else if (IEVersionNum === 10) {
          // IE10
          return 10
      } else {
          // IE版本<7
          return 6
      }
  } else if (isEdge) {
      // edge
      return 'edge'
  } else if (isIE11) {
      // IE11
      return 11
  } else {
      // 不是ie浏览器
      return -1
  }
}

判断当前环境(PC/mobile/微信/企业微信/微信mobile/微信pc/企业微信mobile/企业微信pc)

function envjudge() {
    var isMobile = window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i); // 是否手机端
    var isWx = /micromessenger/i.test(navigator.userAgent); // 是否微信
    var isComWx = /wxwork/i.test(navigator.userAgent); // 是否企业微信
            
    if (isComWx && isMobile) { //手机端企业微信
        return 'com-wx-mobile'
    }
    else if (isComWx && !isMobile) { //PC端企业微信
        return 'com-wx-pc'
    }
    else if (isWx && isMobile) { // 手机端微信
        return 'wx-mobile';
    }
    else if (isWx && !isMobile) { // PC端微信
        return 'wx-pc';
    }
    else {
        return 'other';
    }
}

无刷新替换浏览器地址栏参数

pushState:在浏览器history中有记录
replaceState:直接替换掉当前url,不会在history中留下记录

window.history.pushState(data, title, targetURL);
window.history.replaceState(data, title, targetURL);

var href = window.location.href;
href = href + '&city=北京'
if (window.history) {
	// 支持History API
	window.history.replaceState(null, "", href)
}

浏览器打开发送短信界面/打开拨打电话界面

<a href="sms:15117777777?body=我喜欢你很久了">去发短信</a>
<a href="tel:15117777777">给他打电话</a>
<!-- window.location.href='tel:400-600-9666';-->

替换Html

function replaceHtml(Content, ContentFormat, className) {
    var ret = '';
    className = className || ''
    $.each(ContentFormat,function (index, item) {
        var centerstr = Content.substr(item.Start, item.Length)
        ret += '<span class="' + className+'" style="font-weight:' + (item.Bold ? 'bold' : '500') + ';color:' + item.Color + '">' + centerstr + '</span>'
    });
    return ret;
}
var Content = '原行程(杭州-重庆)与申请单行程(杭州-重庆)不一致,需退订原行程后,再重新预订新的行程。'
var format = [
{Start: 0, Length: 4, Color: "#333333", Bold: false},
{Start: 4, Length: 5, Color: "#FF6E00", Bold: false},
{Start: 9, Length: 8, Color: "#333333", Bold: false},
{Start: 17, Length: 5, Color: "#2A86E8", Bold: false},
{Start: 22, Length: 23, Color: "#333333", Bold: false}
]
replaceHtml(Content,format); 

vue slide动画

参考 动画

<transition name="detail">
    <div class="detail-box" v-show="toggle">
		<Component/>
	</div>
</transition >

<style>
.detail-box{ overflow: hidden; transition: all .2s;}
.detail-enter-from{height: 0px;}
/* .detail-enter-active{} */
.detail-enter-to {height: 300px; }

.detail-leave-from{height: 300px;}
/* .detail-leave-active{} */
.detail-leave-to{height: 0px;}
</style>

三角函数( Math.sin/Math.cos)

-1到1之间
设置一个点在800 x 600 的盒子里面做曲线运动

var num = 0,speed = 3;
var dom = document.querySelector('.btn-publish')
var timer = setInterval(function(){
    if(num >= 5){clearInterval(timer)}
    num  += 0.5; // 累加的值可随意调节
    var disx = 400 - Math.cos(num ) * 400; // 0 - 800之间
 	var disy = 300 - Math.sin(num * speed) * 300; // 0 - 600之间
    dom.style.top = disy +'px'
    dom.style.left= disx  +'px';
},1000)

弧度 = 角度 * Math.PI / 180
角度 = 弧度 * 180 / Math.PI

for(var angle = 0; angle < 360; angle += 30) //  360°,一圈,每次累加30°
    {
        var hd = angle * Math.PI / 180; // 由于sin和cos参数是弧度,所以转成弧度
        var x = Math.cos(hd) * 300; // 由于cos、sin的值在-1到1之间,所以可以适当增大半径
        var y = Math.sin(hd) * 300 + 400; // 默认原心是(0,0),将圆心的y坐标增加400
        points.push([x,y])
    }
    console.log(points); // 所有点坐标都在圆心为(0,400)的弧上

Math.atan2(y2-y1,x2-x1)

返回从原点(0,0)到(x,y)点的线段与x轴正方向之间的平面角度(弧度值),也就是Math.atan2(y,x)

atan2 方法返回一个 -pi 到 pi 之间的数值,表示点 (x, y) 对应的偏移角度。这是一个逆时针角度,以弧度为单位,正X轴和点 (x, y) 与原点连线 之间。注意此函数接受的参数:先传递 y 坐标,然后是 x 坐标。

atan2 接受单独的 x 和 y 参数,而 atan 接受两个参数的比值。

Math.atan2(90, 15) // 1.4056476493802699

dom跟随鼠标移动,每次四舍五入移动25个像素

dom.top= Math.round(moveY/25) *25
dom.left = Math.round(moveX/25) *25

获取随机颜色

0xff6600: 是16进制,显示橘黄色,转成10进制 parseInt(‘ff6600’,16), 结果是 16737792
所以 0xff6600 和16737792是同一个颜色
黑色0x000000 => 0
白色0xffffff => 16777215

16777215 转 0xffffff 也很简单
(16777215 ).toString(16)

// 随机获取一个颜色
var color1 = '#' + (rangeRandom(0, 16777215)).toString(16)
var color2 = '0x' + (rangeRandom(0, 16777215)).toString(16)

function rangeRandom (m,n){
  return Math.floor(Math.random()*(m - n) + n);
}

获取元素某一事件上绑定的所有Listener

浏览器console命令行里面输入下面代码
getEventListeners(document.querySelector('.item'))

给字符串中的某一段字符添加样式,包头不包尾

function resetContent(Content, Styles) {
  const o = []
  let tagIndex = 0;

  Styles.forEach((t, index) => {
    if (tagIndex !== t.Begin) {
      o.push({
        Content: Content.substr(tagIndex, t.Begin - tagIndex),
        Style: null
      })
      tagIndex = t.End;
    }

    o.push({
      Content: Content.substr(t.Begin, t.End - t.Begin),
      Style: { color: t.Color }
    })

    if (index === Styles.length - 1) {
      if (t.End <= Content.length - 1) {
        o.push({
          Content: Content.substr(t.End, Content.length - t.End),
          Style: null
        })
      }
    }
  })
  return o;
}
调用:
const con = "服务车型(商务型)不符合差标(经济型、优享型、品质专车)"
const styles = [{Color: "#FF6E00", Begin: 5, End: 8},{Color: "#2A86E8", Begin: 15, End: 23}]
resetContent(con ,styles)

localstorage.setItem设置监听事件

const localStorageSetItem = localStorage.setItem
localStorage.setItem = function (key, val) {
  const event = new Event('localStorageSetItem');
  event.storageKey = key;
  event.storageVal = val;
  window.dispatchEvent(event)
  localStorageSetItem.apply(this, arguments)
}

window.addEventListener('localStorageSetItem', (e) => {
  console.log(e);
})

数字生成数字数组,对象转数组

const count = 5;
const arr = [...Array(count).keys()]
const o = {a:1,b:2,c:3}
Object.keys(o); // ['a', 'b', 'c']
Object.values(o); // [1, 2, 3]

滑动过程中,模拟惯性

let deltaYTime = 0;
let deltaDistance = 0;
let MoveY = 0;
const onTouchStart = (e) => {
	deltaYTime = Date.now();
	deltaDistance = 0;
}

const onTouchMove = (e) => {
 // 滑动的过程中,如果超过200毫秒就重置deltaDistance,
 // 最后一次滑动,到手指抬起,时间不超过200毫秒的话,就当做是在快速滑动
    MoveY = e.touches[0].clientY
	const now = Date.now();
	if (now - deltaYTime > 200) {
		deltaYTime = now;
		deltaDistance = e.touches[0].clientY;
	}
}

const onTouchEnd = () => {
// speed 越大,速度越快
 const speed = Math.abs(MoveY - deltaDistance) / (Date.now() - deltaYTime)
	offsetY = speed > 2 ? dixY * speed : dixY ;
}

已知两个点求其三等分点

A1(X1,Y1,Z1),A2(X2,Y2,Z2)
三等分点为A3(X3,Y3,Z3),A4(X4,Y4,Z4)
X3=(X2+2X1)/3,Y3=(Y2+2Y1)/3,Z3=(Z2+2Z1)/3
X4=(2X2+X1)/3,Y4=(2Y2+Y1)/3,z4=(2Z2+Z1)/3


const bulge = 1.48; // 中间部分弧往外凸出
const dn = 7; // 8分之一处的点
const dbulge = 1.15; // 两边的点弧往外凸出

const curve = new THREE.CatmullRomCurve3([
  // 起始点
  new THREE.Vector3(
    this.fromPosition.x,
    this.fromPosition.y,
    this.fromPosition.z
  ),
  // 八分之一出的点
  new THREE.Vector3(
    ((dn * this.fromPosition.x + this.toPosition.x) / (dn + 1)) * dbulge,
    ((dn * this.fromPosition.y + this.toPosition.y) / (dn + 1)) * dbulge,
    ((dn * this.fromPosition.z + this.toPosition.z) / (dn + 1)) * dbulge
  ),
// 中心点
  new THREE.Vector3(
    ((this.fromPosition.x + this.toPosition.x) / 2) * bulge,
    ((this.fromPosition.y + this.toPosition.y) / 2) * bulge,
    ((this.fromPosition.z + this.toPosition.z) / 2) * bulge
  ),
// 八分之七处的点
  new THREE.Vector3(
    ((this.fromPosition.x + dn * this.toPosition.x) / (dn + 1)) * dbulge,
    ((this.fromPosition.y + dn * this.toPosition.y) / (dn + 1)) * dbulge,
    ((this.fromPosition.z + dn * this.toPosition.z) / (dn + 1)) * dbulge
  ),
// 结束点
  new THREE.Vector3(
    this.toPosition.x,
    this.toPosition.y,
    this.toPosition.z
  ),
]);

已知两个点,两点中心点到(0,0,0)的中心点

A1(X1,Y1,Z1),A2(X2,Y2,Z2)
 // 两点之间的中点
  const center = {
    x: (X1 + X2) / 2,
    y: (Y1 + Y2) / 2,
    z: (Z1 + Z2) / 2,
  };
 // (0,0,0)到center之间的中点
 const originTocenter = {
   x: (0 + center.x) / 2,
   y: (0 + center.y) / 2,
   z: (0 + center.z) / 2,
 };
  • 3
    点赞
  • 14
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论

打赏作者

榴莲不好吃

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值