手机网站图片切换jquery/微信公众号的推广

手机网站图片切换jquery,微信公众号的推广,建站网站免费,讯代理网站文章简述 这是本人自己封装的时间轴2.0版本的代码,用到了TypeScriptJavaScript 这篇文章只有代码和具体的使用方式,如果想看具体的讲解可以参考本人写的时间轴1.0版本的,在1.0版本中可能计算时间线的逻辑略有不同,但是大致的计算…
文章简述

这是本人自己封装的时间轴2.0版本的代码,用到了TypeScript+JavaScript

这篇文章只有代码和具体的使用方式,如果想看具体的讲解可以参考本人写的时间轴1.0版本的,在1.0版本中可能计算时间线的逻辑略有不同,但是大致的计算逻辑都一样
时间轴1.0

主要内容
具体代码
/*** 时间轴*/
type TimeLineParamsType = {reviewNum: number,MouseDownfn: Function,MouseUpfn: Function,CustomReMindLabelfn: Function,level: number,stepLength: number,timeSwitchContent: Function,CanvasConfigParams: Partial<CanvasConfigParamsType>,baseDate: Date,isCanvas: boolean
}
type GradientModeType = 'linear' | 'radial' | 'conic'
type CanvasConfigParamsType = {fontSize: string,scale_fontColor: string,scale_strokeColor: string,scale_lineWidth: number,scale_lineLength: number,tl_Height: number,tl_strokeColor: string,tl_strokeWidth: number,tl_fillColor: string,pg_fillColor: string,pg_gradientMode: GradientModeType,pg_gradientColors: string[],isGradient: boolean,tl_radius: number
}export class useTimeLine {/*** 基时间* @description 如果没有则使用当前时间 */baseDate: Date | null = null/*** 时间数组*/DateArray: string[] = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]/*** 记录单位的数组 ["号","周","月","年"]*/UnitArray: string[] = ["号", "周", "年", "年"]/*** 是否使用吸附效果*/isAdsorb = false/*** 记录是否是初次加载 默认:是*/#isInitLoad: boolean = true;/*** 当前显示时间轴的级别,默认:1*/TimeLevel: number = 1;/*** 最外层的元素元素*/ParentNode: HTMLElement | null;/*** 需要显示未来几天的数据*/ReviewNum: number = 10;/*** 每个时间段需要的长度*/TimeSlotWidth: number = 0/*** 每个时间段又分出多少间隔,默认:24*/TimeSlotInterval: number = 60;/*** 时间段中每个间隔的长度*/TimeSlotIntervalWidth: number = 0;/*** 保存当前时间进度*/CurrentTimeProgress: number = 0;/*** 时间轴的步长*/TimeStepLength = 1;/*** 时间轴移动的速度*/TimeMoveSpeed: number = 2000;/*** 保存当前的移动进度*/CurrentDay: number = 0;/*** 要显示的宏观文本数组--就是时间轴中最高级的显示单位*/MacroTextArray: string[] = []/*** 要显示的微观数组*/DateTextArray: number[] = []/*** 当前的canvas对象*/_CanvasContent: CanvasRenderingContext2D | null = null/*** 是否使用canvas做时间轴*/isCanvas = false;/*** 计算进度条时左边距-不用动*/#CanvasMarginLeft = 60;/*** 时间轴的路径对象*/TimeLinePath: Path2D | null = null;/*** 参数配置对象*  fontSize: 时间轴下方提示标尺的字体大小,*  scale_fontColor: 时间轴下方提示标尺的字体颜色scale_strokeColor: 标尺线的颜色,scale_lineWidth: 标尺线的宽度,scale_lineLength: 标尺线的高度,tl_Height: 时间轴的高度--进度条背景板,tl_strokeColor: 绘制时间轴时的线颜色 - 此属性必须配合tl_strokeWidth属性一起使用,tl_strokeWidth: 绘制时间轴时的线宽,tl_fillColor: 绘制时间轴时的填充颜色,pg_fillColor: 进度条的颜色pg_gradientMode: 进度条的渐变色的模式,pg_gradientColors: ['#cd1919', '#1977cd', '#f70da2'],isGradient: 是否使用渐变色tl_radius: 时间轴的边缘弧度*/CanvasConfigParams: CanvasConfigParamsType = {fontSize: '',scale_fontColor: '#fff',scale_strokeColor: '',scale_lineWidth: 0,scale_lineLength: 5,tl_Height: 10,tl_strokeColor: '',tl_strokeWidth: 0,tl_fillColor: '',pg_fillColor: '',pg_gradientMode: 'radial',pg_gradientColors: ['#cd1919', '#1977cd', '#f70da2'],isGradient: false,tl_radius: 20}/*** 时间轴与鼠标交互时的元素*/time_progressbar_tooltip: HTMLElement | null = null;/*** 覆盖在时间轴元素上方*/t_progressbar: HTMLElement | null = null;/*** 自动播放按钮的点击状态回调* @param {*} flag  点击状态 播放:true 停止:false* @param {*} target 当前的元素*/autoPlayClickStatus: Function | null = null;/*** 点击的状态*/autoClickStatus: boolean = true;/*** 往自动播放按钮元素中添加元素的方法*/timeSwitchContent: Function | null = null;/*** @description tooltip更换显示dom* @description tip:请返回string形式的dom* @param {object} e macro:最宏观的显示单位 day:中等显示单位 date:最小显示单位*/setTooltipElementFn: Function | null = null;/*** 自定义时间轴底部的显示内容* @param {object} macro 当前的宏远显示单位* @param {object} secondary 当前二级显示单位  */CustomReMindLabelfn: Function | null = null;/*** 鼠标点下的回调方法*/MouseDownfn: Function | null = null;/*** 鼠标松开的回调方法*/MouseUpfn: Function | null = null/*** 生成时间轴* @param eleId 最外层的id * @param reviewNum 要显示的天数* @param level 可选参数- 显示的层级* @returns useTimeLine*/constructor(eleId: string, params: Partial<TimeLineParamsType>) {this.ParentNode = this.getById(eleId);if (!this.ParentNode) return this;this.init(params);return this;}init(params?: Partial<TimeLineParamsType>) {this.setGlobalConfigs(params)// 根据层级编辑展示信息数组this.useTimeShowTextByLevel()// 如果不是第一次加载--先销毁先前添加的事件this.DestoryTimeLine(this.#isInitLoad)// 往父元素中添加内容this.ParentNode?.appendChild(this.createElement() as HTMLDivElement)// 添加时间轴底部的信息展示框this.MakeReMindElement()// 添加鼠标事件this.addEventMouse()// 开关添加点击事件this.SwitchAddClick();this.ParentNode && this.ElementAddProxy(this.ParentNode)// 改变是否初次加载的值,变为falsethis.#isInitLoad = false;}/*** @param {*} params*/setGlobalConfigs(params?: Partial<TimeLineParamsType>) {if (!params) return false;let { reviewNum, MouseDownfn, MouseUpfn, CustomReMindLabelfn, level, stepLength, timeSwitchContent, CanvasConfigParams, baseDate, isCanvas } = params;this.ReviewNum = reviewNum || this.ReviewNum;this.TimeLevel = level !== void 0 ? level : this.TimeLevelthis.TimeStepLength = stepLength || this.TimeStepLengththis.CustomReMindLabelfn = CustomReMindLabelfn instanceof Function ? CustomReMindLabelfn : nullthis.timeSwitchContent = timeSwitchContent instanceof Function ? timeSwitchContent : null;this.MouseDownfn = MouseDownfn instanceof Function ? MouseDownfn : null;this.MouseUpfn = MouseUpfn instanceof Function ? MouseUpfn : null;this.CanvasConfigParams = { ...this.CanvasConfigParams, ...CanvasConfigParams }this.baseDate = baseDate || this.baseDate || new Date();this.isCanvas = typeof isCanvas === "boolean" ? isCanvas : this.isCanvas || false;}/*** 按照显示级别来给时间轴设置显示文本*/useTimeShowTextByLevel(level?: number) {let l = level ? level : this.TimeLevel;switch (l) {case 0:this.setDateTextArrayZore()// 一个小时有60分钟 this.TimeSlotInterval = 60;break;case 1:this.setDateTextArrayOne()// 一天有24小时this.TimeSlotInterval = 24;break;case 2:this.setDateTextArrayTwo()// 一月有30天,但是每个月有特殊性this.TimeSlotInterval = 30;break;case 3:this.setDateTextArrayThree()// 一月有30天,但是每个月有特殊性this.TimeSlotInterval = 12;break;default:throw new Error("当前显示设置级别不合理")break;}}ElementAddProxy(target: HTMLElement) {if (!target) return false;let self = this;// let observer = new MutationObserver((mutationList) => {// 	observer.disconnect()// 	console.log("html元素尺寸发生变化:", mutationList)//     self.init()// })// observer.observe(target, { attributes: true, subtree:true,characterData:true, attributeFilter: ['style'], attributeOldValue: true })// // 观察目标节点的变化const observer = new MutationObserver(mutations => {mutations.forEach(mutation => {if (mutation.attributeName === 'style') {observer.disconnect()self.init()}});});const config = {attributes: true,  //监听元素的属性有没有变化attributeFilter: ['style'],characterData: true,};observer.observe(target, config);}/*** @description 鼠标是否可以拖动时间轴的条件* @description true:允许* @description false:禁止*/TimeMouseDownFlag = false;// 为时间轴添加鼠标相应的事件addEventMouse() {let time_progressbar = this.getByClass("TimeLineProgressbar")if (!time_progressbar || time_progressbar.length == 0) return false;// 因为使用addEventListener来绑定事件,所以使用bind来更改this的指向(time_progressbar[0] as HTMLElement).addEventListener("mousedown", this.Time_MouseDown.bind(this))window.addEventListener("mousemove", this.WindowMouseMove_time.bind(this))window.addEventListener("mouseup", this.WindowMouseUp_time.bind(this))return true;}/*** window上的鼠标移动事件*/WindowMouseMove_time(e: MouseEvent) {let self = this;if (!self.TimeMouseDownFlag) return false;e.preventDefault()this.#currentTargetOffset && self.updataElementStatus(e.pageX - this.#currentTargetOffset.left)}/*** window上的鼠标松开事件*/WindowMouseUp_time(e: MouseEvent) {this.MouseUpfn && this.MouseUpfn(e)this.TimeMouseDownFlag = false;}#currentTargetOffset: { width: number, height: number, top: number, left: number } | null = null;/*** 时间轴上的鼠标按下事件*/Time_MouseDown(e: MouseEvent) {let self = this;// 判断点击位置是否在路径内if (!this.isPointInPath(this.TimeLinePath, e.offsetX, e.offsetY)) return false;this.MouseDownfn && this.MouseDownfn(e)self.TimeMouseDownFlag = true;self.#currentTargetOffset = (e.currentTarget as HTMLElement)?.getBoundingClientRect();e.preventDefault()self.updataElementStatus(e.offsetX)}// 给时间轴的开关添加点击事件SwitchAddClick() {let self = this;let time_switch = this.getByClass("time_switch")[0] as HTMLDivElement;if (!time_switch) {setTimeout(() => {self.SwitchAddClick()}, 1000)return false;}if (time_switch == null) return false;time_switch.addEventListener("click", this.timeSwitchClickHandle.bind(this))return true;}timeSwitchClickHandle(e: MouseEvent) {this.autoUpdateTimeStatus(this.autoClickStatus);this.autoPlayClickStatus instanceof Function && this.autoPlayClickStatus(this.autoClickStatus, e.currentTarget, e)this.autoClickStatus = !this.autoClickStatus;}/*** 创建指定的元素*/createElement() {if (!this.ParentNode) return false;let { width, height } = this.ParentNode.getBoundingClientRect();// 最外层的元素let timeLine = document.createElement("div");timeLine.classList.add('timeLine')// 控制时间轴的开关let time_switch = document.createElement("div");time_switch.classList.add('time_switch')this.timeSwitchContent && (time_switch.innerHTML = this.timeSwitchContent(time_switch))timeLine.appendChild(time_switch)// 时间轴线的外层元素let time_content = document.createElement("div");time_content.classList.add('time_content')!this.isCanvas && time_content.classList.add('time_content_flex')timeLine.appendChild(time_content)// 最下面的问题提示元素--周一--周二let time_progressbar_remind = document.createElement("div");time_progressbar_remind.classList.add('time_progressbar_remind')// 时间轴与鼠标交互时的元素this.time_progressbar_tooltip = document.createElement("div");this.time_progressbar_tooltip.classList.add('time_progressbar_tooltip')// 时间轴线let time_progressbar;if (this.isCanvas) {time_progressbar = document.createElement("canvas");this._CanvasContent = time_progressbar.getContext("2d");time_progressbar.classList.add('TimeLineProgressbar')time_progressbar.width = width - 60;time_progressbar.height = height;this.drawTimeLineByCanvas();} else {time_progressbar = document.createElement("div");time_progressbar.classList.add('time_progressbar')time_progressbar.classList.add('TimeLineProgressbar')// 覆盖在时间轴元素上方this.t_progressbar = document.createElement("div");this.t_progressbar.classList.add('t_progressbar')time_progressbar.appendChild(this.t_progressbar)}time_content.appendChild(this.time_progressbar_tooltip)time_content.appendChild(time_progressbar)time_content.appendChild(time_progressbar_remind)return timeLine;}/*** 绘制canvas时间轴*/drawTimeLineByCanvas(progress = 0) {let { tl_Height, tl_strokeColor, tl_strokeWidth, tl_radius, tl_fillColor, pg_fillColor, isGradient } = this.CanvasConfigParams;// 绘制进度条if (!this._CanvasContent || !this.ParentNode) return false;let { width, height } = this.ParentNode.getBoundingClientRect();width = Math.floor(width - this.#CanvasMarginLeft);this.TimeLinePath = new Path2D();let roundLeft = 0;let ctx = this._CanvasContent;ctx.clearRect(roundLeft, (height / 2) - tl_Height / 2, width, tl_Height)ctx.save()ctx.beginPath();ctx.strokeStyle = tl_strokeColor || "red"ctx.lineWidth = tl_strokeWidth || 0;ctx.fillStyle = tl_fillColor || "#666"this.TimeLinePath.roundRect(roundLeft, (height / 2) - tl_Height / 2, width, tl_Height, tl_radius)ctx.closePath();ctx.fill(this.TimeLinePath);tl_strokeWidth && ctx.stroke(this.TimeLinePath);ctx.restore()// 绘制进度ctx.save()ctx.fillStyle = isGradient ? this.createGradient(roundLeft, (height / 2) - tl_Height / 2, progress, tl_Height) as CanvasGradient : pg_fillColor || "red"ctx.beginPath();ctx.roundRect(roundLeft, (height / 2) - tl_Height / 2, progress, tl_Height, tl_radius)ctx.fill();ctx.restore()}/*** 添加时间提示dom* @returns */MakeReMindElement() {if (this.isCanvas) {this.#_MakeScaleCanvas()} else {this.#_MakeScaleElement()}}#_MakeScaleCanvas() {if (!this._CanvasContent || !this.ParentNode) return false;let ctx = this._CanvasContent;let { fontSize, scale_fontColor, scale_strokeColor, tl_Height, scale_lineWidth, scale_lineLength } = this.CanvasConfigParams;let { width, height } = this.ParentNode.getBoundingClientRect();width = width - this.#CanvasMarginLeft;// 绘制标尺this.TimeSlotWidth = width / this.ReviewNum;this.TimeSlotIntervalWidth = Number((this.TimeSlotWidth / this.TimeSlotInterval).toFixed(2))ctx.save()ctx.font = `${fontSize}px 微软雅黑`;for (let i = 0; i < this.ReviewNum; i++) {let x = (i * this.TimeSlotWidth * 1);let y = height / 2;ctx.strokeStyle = scale_strokeColor || "red"ctx.lineWidth = scale_lineWidth || 2ctx.beginPath();ctx.moveTo(x, y + tl_Height / 2)ctx.lineTo(x, y + tl_Height / 2 + scale_lineLength)let text = (this.CustomReMindLabelfn instanceof Function) ?this.CustomReMindLabelfn(this.MacroTextArray[i], this.DateTextArray[i]) :this.UnitArray[this.TimeLevel] + (Number(this.MacroTextArray[i]) + 1) + (this.DateTextArray[i] ? this.DateTextArray[i] : '')let { width: mt_width } = ctx.measureText(text)ctx.fillStyle = scale_fontColor || "#000"ctx.fillText(text, Math.max(0, x - mt_width / 2) && Math.min(width, x - mt_width / 2), y + 20)ctx.stroke();}ctx.restore()}#_MakeScaleElement() {let rect = this.getElementRectById("time_content");if (rect == null) return false;this.TimeSlotWidth = rect?.width / this.ReviewNum;this.TimeSlotIntervalWidth = Number((this.TimeSlotWidth / this.TimeSlotInterval).toFixed(2))let time_progressbar_remind = this.getByClass("time_progressbar_remind")[0];for (let i = 0; i < this.ReviewNum; i++) {let span = document.createElement("span");span.innerText = (this.CustomReMindLabelfn instanceof Function) ?this.CustomReMindLabelfn(this.MacroTextArray[i], this.DateTextArray[i]) :this.UnitArray[this.TimeLevel] + (Number(this.MacroTextArray[i]) + 1) + (this.DateTextArray[i] ? this.DateTextArray[i] : '')span.style.cssText = `width:${this.TimeSlotWidth}px;`time_progressbar_remind?.appendChild(span)}}// 自动播放的定时器id,方便清除定时器_setInterval: number = -1;/*** 自动修改时间轴状态* @param flag */autoUpdateTimeStatus(flag: boolean) {let self = this;if (flag) {// 某个时间段内的进一步的值let IntervalWidth = this.TimeSlotIntervalWidth * this.TimeStepLength;if (this.TimeLevel == 2) {let curr_monthDay = this.getDaysByMonth(this.CurrentDay);IntervalWidth = curr_monthDay / this.TimeSlotWidth;}let len = self.CurrentTimeProgress + IntervalWidth;let totalLen = self.TimeSlotWidth * self.ReviewNum;if (len >= totalLen) len = 0;self.updataElementStatus(len)self._setInterval && clearInterval(self._setInterval);self._setInterval = setInterval(() => {self.autoUpdateTimeStatus(flag);}, self.TimeMoveSpeed)} else {clearInterval(self._setInterval)}}/*** 修改时间轴的位置-进度* @param PosiX * @returns */updataElementStatus(progress: number) {let _progress = progress;this.CurrentTimeProgress = _progress;this.updataShowTooltip(_progress)}/*** 定时器的id,* 控制tip元素的消失*/_setTimeoutId: number = -1;/*** 更改tip元素样式* @param progress* @returns */updataShowTooltip(progress: number) {let self = this;let _progress = progress;if (this.time_progressbar_tooltip == null) return false;let rect = self.getDateByOffsetX(_progress);let { isNotAchieve, length } = this.getLengthByDate(rect);if (isNotAchieve && this.isAdsorb) rect = self.getDateByOffsetX(length)this.time_progressbar_tooltip.innerHTML = (self.setTooltipElementFn instanceof Function && self.setTooltipElementFn(rect)) || `日期:${rect.day - 1}<br />时间:${rect.date}`let tooltip_rect = this.getElementRectById("time_progressbar_tooltip");if(this.isCanvas){this.drawTimeLineByCanvas(length);}else{if (this.t_progressbar) this.t_progressbar.style.cssText = `width:${length}px;`}(this.time_progressbar_tooltip).style.cssText = `z-index:999;width:7%;opacity:1;left:${length}px;top:-${(tooltip_rect.height) + 10}px`if (this._setTimeoutId != 0) clearTimeout(self._setTimeoutId);this._setTimeoutId = setTimeout(() => {clearTimeout(self._setTimeoutId)if (self.time_progressbar_tooltip == null) return false;(self.time_progressbar_tooltip).style.cssText = "opacity:0,z-index:-1;"}, 2000)}/*** @description 将长度转换为时间* @description 本长度的起点是指时间线0点距离,不是屏幕的0点* @param {*} offsetX*/getDateByOffsetX(offsetX: number) {// 跨越的时间段let timeSolt = Math.floor(offsetX / this.TimeSlotWidth);// 剩余的时间段距离let _timeSolt = offsetX % this.TimeSlotWidth;let macro = this.MacroTextArray[Math.floor(timeSolt)];let day = this.DateTextArray[timeSolt] + 1;// 记录下当前走到哪里了this.CurrentDay = day;// 具体时间let date = Math.floor(_timeSolt / this.TimeSlotIntervalWidth);// 如果时间轴的层级是2,则因为月份会有不同,因此要使用另一种计算方法if (this.TimeLevel == 2) {let a = this.getDaysByMonth(this.DateTextArray[Math.floor(timeSolt)])let b = a / this.TimeSlotWidth;date = (Math.ceil(_timeSolt * b) % a) + 1;}return {macro,day,date}}/*** 将时间转换为长度*/getLengthByDate({ macro, day, date }: { macro: string, day: number, date: number }) {// 计算宏观时间的总长度let macroTotal = 0;const _day = Number(day) - 1;// 计算在时间数组中的位置let timeSlotIndex = 0;for(let i = 0; i < this.DateTextArray.length; i++) {if(this.DateTextArray[i] === _day && this.MacroTextArray[i] === String(macro)) {timeSlotIndex = i;break;}}// 计算宏观长度macroTotal = timeSlotIndex * this.TimeSlotWidth;// 计算具体时间的长度let timeTotal = 0;switch(this.TimeLevel) {case 0: // 分钟timeTotal = (date / 60) * this.TimeSlotWidth;break;case 1: // 小时timeTotal = (date / 24) * this.TimeSlotWidth;break;case 2: // 天const daysInMonth = this.getDaysByMonth(_day);timeTotal = (date / daysInMonth) * this.TimeSlotWidth;break;case 3: // 月timeTotal = (date / 12) * this.TimeSlotWidth;break;}// 计算总长度const totalLength = macroTotal + timeTotal;// 处理吸附效果if(this.isAdsorb) {const stepWidth = this.TimeSlotIntervalWidth * this.TimeStepLength;const steps = Math.round(totalLength / stepWidth);const snapLength = steps * stepWidth;return {isNotAchieve: Math.abs(totalLength - snapLength) > 1,length: snapLength};}return {isNotAchieve: false,length: totalLength};}/*** 设置显示的时间文本数组* 0级*/setDateTextArrayZore() {let date = this.baseDate || new Date();// 月份let month = date.getMonth() + 1;// 小时let hours = date.getHours();this.MacroTextArray = []this.DateTextArray = []for (let i = 0; i < this.ReviewNum; i++) {this.MacroTextArray.push(month + '')this.DateTextArray.push(hours)hours += 1;if (hours == 24) {month++hours = 0;}}}/*** 设置显示的时间文本数组* 1级*/setDateTextArrayOne() {let date = this.baseDate || new Date();// 周几let week = date.getDay();// 几号 ,因为下面会+1 因此这里要 -1let day = date.getDate() - 1;// 月份let month = date.getMonth() + 1;// 本月的天数let monthDay = this.getDaysByMonth(month);let _monthDay = 0;this.MacroTextArray = []this.DateTextArray = []for (let i = 0; i < this.ReviewNum; i++) {this.MacroTextArray.push(((week + i) % 7) + '')_monthDay++;// 避免月份出错if (_monthDay > monthDay) {month++monthDay = this.getDaysByMonth(month);_monthDay = 0;}this.DateTextArray.push(((day + i) % (monthDay)) + 1)}}/*** 设置显示的时间文本数组* 2级*/setDateTextArrayTwo() {let date = this.baseDate || new Date();// 月份let month = date.getMonth() + 1;// 年份let year = date.getFullYear();this.MacroTextArray = []this.DateTextArray = []for (let i = 0; i < this.ReviewNum; i++) {this.MacroTextArray.push(year + '')this.DateTextArray.push(month)month += 1if (month == 13) {year++month = 1}}}/*** 设置显示的时间文本数组* 3级*/setDateTextArrayThree() {let date = this.baseDate || new Date();// 年份let year = date.getFullYear();this.MacroTextArray = []this.DateTextArray = []for (let i = 0; i < this.ReviewNum; i++) {this.MacroTextArray.push(year + '')this.DateTextArray.push(0)year++}}/*** 通过月份来返回本月的时间* @param month 月份* @returns 本月的时间*/getDaysByMonth(month: number) {let a = [1, 3, 5, 7, 8, 10, 12];let b = [2]if (a.includes(month)) {return 31} else if (b.includes(month)) {return this.#isLeapYear(this.baseDate?.getFullYear()) ? 29 : 28} else {return 30}}/*** 判断当前是否是闰年* @param year * @returns */#isLeapYear(year: number | undefined) {if (!year) return false;let _year = Number(year)return (_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0) ? true : false}/*** 判断点是否在指定路径内*/isPointInPath(...args: any[]) {if (!this.isCanvas || !this._CanvasContent) return true;let [path, x, y] = args;if (path instanceof Path2D) {return this._CanvasContent.isPointInPath(path, x, y);} else {return this._CanvasContent.isPointInPath(args[0], args[1]);}}/*** 生成渐变色* @param x0 起始点x* @param y0 起始点y* @param x1 结束点x* @param y1 结束点y* @returns */createGradient(x0: number, y0: number, x1: number, y1: number) {let { pg_gradientMode, pg_gradientColors } = this.CanvasConfigParams;let gradient: CanvasGradient | null = this.makeGridentObjectByMode(pg_gradientMode, x0, y0, x1, y1);if (!gradient) return ''let average = 1 / pg_gradientColors.length;pg_gradientColors.forEach((item, index) => {gradient.addColorStop(average * index, item)})return gradient;}/*** 根据模式返回相关的渐变色对象*/makeGridentObjectByMode(mode: GradientModeType, ...args: any[]): CanvasGradient | null {let [x0, y0, x1, y1] = args;let canvasGridentMode: GradientModeType[] = ['linear', 'radial', 'conic']if (!canvasGridentMode.includes(mode)) throw new Error(`渐变的模式必须是${canvasGridentMode.join(',')}的其中一种`)if (!this._CanvasContent) return null;let ctx = this._CanvasContent;// 计算中心点let center = {x: (x1 - x0) / 2,y: (y1 - y0) / 2}let result = null;switch (mode) {case "linear":result = ctx.createLinearGradient(x0, y0, x1, y1)case 'radial':result = ctx.createRadialGradient(x0, y0, 20, x1, y1, center.x)case 'conic':result = ctx.createConicGradient(0, center.x, center.y)}return result;}/*** 通过id查找元素* @param id * @param flag 是否往时间轴最外层元素中找元素* @returns */getById(id: string, flag = true) {let n = flag ? document : this.ParentNode;return n && (n as Document).getElementById(id);}/*** 通过class查找元素* @param className * @returns */getByClass(className: string) {if (this.ParentNode == null) return [];return this.ParentNode.getElementsByClassName(className);}/*** 通过id获取元素的具体信息* @param id * @returns */getElementRectById(id: string) {let e = this.getByClass(id);return e && e[0].getBoundingClientRect();}/*** 销毁时间线中实例和绑定的事件*/DestoryTimeLine(flag?: boolean) {if (flag) return false;let time_progressbar = this.getByClass("time_progressbar")time_progressbar[0] && (time_progressbar[0] as HTMLElement).removeEventListener("mousedown", this.Time_MouseDown)window.removeEventListener("mousemove", this.WindowMouseMove_time)window.removeEventListener("mouseup", this.WindowMouseUp_time)// 删除自动播放开关的事件let time_switch = this.getByClass("time_switch")[0];(time_switch as HTMLDivElement).removeEventListener("click", this.timeSwitchClickHandle)this.setTooltipElementFn = null;// 将播放标识恢复初始化this.autoClickStatus = true;this.autoUpdateTimeStatus(false);// 将进度归零this.CurrentTimeProgress = 0;// 清空父元素if (this.ParentNode) this.ParentNode.innerHTML = "";}
}
使用方式
// 引入时间轴组件代码
import { useTimeLine } from '@/hook/TimeLine'// 使用方式
new useTimeLine(dom || 'id名',options)
options配置项
options = {reviewNum:'要显示多少天或时间的内容',isCanvas:'是否用canvas来绘制,默认false',level:'当前的层级,0-3级,默认:1',isAdsorb:'是否使用吸附效果,当我们的步长不为1时,当前效果可用,默认:false',TimeStepLength:'时间轴的步长,有时候需要和isAdsorb参数一起使用,默认:1',baseDate:'配置基本事件,从什么时间开始计算,默认当前时间',TimeMoveSpeed:'时间轴移动的速度,单位是(秒),默认2000',CanvasConfigParams:'如果使用canvas来渲染时,通过此参数可以配置其样式'}CanvasConfigParams = {fontSize: '时间轴下方提示标尺的字体大小',scale_fontColor: '时间轴下方提示标尺的字体颜色',scale_strokeColor: '标尺线的颜色',scale_lineWidth: '标尺线的宽度',scale_lineLength: '标尺线的高度',tl_Height: '时间轴的高度--进度条背景板',tl_strokeColor: '绘制时间轴时的线颜色 - 此属性必须配合tl_strokeWidth属性一起使用',tl_strokeWidth: '绘制时间轴时的线宽',tl_fillColor: '绘制时间轴时的填充颜色',pg_fillColor: '进度条的颜色',pg_gradientMode: '进度条的渐变色的模式',pg_gradientColors: ['#cd1919', '#1977cd', '#f70da2'],isGradient: '是否使用渐变色',tl_radius: '时间轴的边缘弧度'
}
时间轴的回调方法
autoPlayClickStatus: 自动播放按钮的点击状态回调,需要一个方法,参数是点击状态 播放:true 停止:false
// 使用方式:useTime_xxx.autoPlayClickStatus = (flag:boolean)=>{}timeSwitchContent:往自动播放按钮中添加元素,当前组件自带的自动播放按钮是白色圆形,比较丑,可用用此方法重新添加元素
// 使用方式 useTime_xxx.timeSwitchContent = ()=>{ return <div>播放按钮</div>}setTooltipElementFn:当时间轴的长度发生变化时弹出的提示框,可通过此方法修改弹出内容
// 使用方式 useTime_xxx.setTooltipElementFn = ({ day, macro, date })=>{ return `<div>当前时间是${day - 1}</div>`}CustomReMindLabelfn:时间轴底部显示的内容
// 使用方式 useTime_xxx.CustomReMindLabelfn = (o1, o2)=>{ return o2}MouseDownfn:鼠标点击时间轴时的回调MouseUpfn:鼠标按下的回调
简单使用示例
// 准备一个容器
<div id="timeline"></div>
// JavaScript代码
let useTime = new useTimeLine('timeline',{reviewNum:24,isCanvas:false,level:0,CustomReMindLabelfn: (o1, o2) => {// 时间轴底部要显示的内容return o2 % len === 0 ? `${o2}` : ''}
})/*** 时间轴弹出框的显示内容* { day, macro, date } 这些值会根据层级配置的不同返回不同可用的数值*/
useTime.setTooltipElementFn = function ({ day, macro, date }) {let _baseDate = new Date();_baseDate.setMonth(_baseDate.getMonth() + Number(macro) - 1)return `${macro}${day - 1}点:${date}`;
}
文章感想

当前的组件只是本人用自己所学所用的知识编写的,主要是用来给自己做个笔记,等用到时可以直接拿来使用。功用性可能并不是很好,所以如果有哪位同行想使用这段代码插件,并发现问题请和我沟通,我会立刻出来更改,提前感谢各位大佬的指导

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型的压缩技术

尽管人们对越来越大的语言模型一直很感兴趣&#xff0c;但MistralAI 向我们表明&#xff0c;规模只是相对而言的&#xff0c;而对边缘计算日益增长的兴趣促使我们使用小型语言获得不错的结果。压缩技术提供了一种替代方法。在本文中&#xff0c;我将解释这些技术&#xff0c;并…

大华HTTP协议在智联视频超融合平台中的接入方法

一. 大华HTTP协议介绍 大华HTTP协议是大华股份&#xff08;Dahua Technology&#xff09;为其安防监控设备开发的一套基于HTTP/HTTPS的通信协议&#xff0c;主要用于设备与客户端&#xff08;如PC、手机、服务器&#xff09;之间的数据交互。该协议支持设备管理、视频流获取、…

7、vue3做了什么

大佬认为有何优点&#xff1a; 组合式api----逻辑集中、对ts有更好的支持RFC–开放了一个讨论机制&#xff0c;可以看到每一个api的提案&#xff0c;方便源码维护&#xff0c;功能扩展&#xff0c;大家一起讨论 官方rfc响应式独立&#xff0c;new Proxy&#xff0c;天生自带来…

多人在线聊天系统,创建群,视频,语音,自带带授权码

多人在线聊天系统&#xff0c;创建群&#xff0c;视频&#xff0c;语音 带授权码&#xff0c;授权码限制 10 个网站&#xff0c;需要下载研究吧 在线聊天&#xff0c;创建群&#xff0c;表情&#xff0c;图片&#xff0c;文件&#xff0c;视频&#xff0c;语音&#xff0c;自…

NFC 碰一碰发视频源码搭建,支持OEM

一、引言 NFC&#xff08;Near Field Communication&#xff09;近场通信技术&#xff0c;以其便捷、快速的数据交互特性&#xff0c;正广泛应用于各个领域。其中&#xff0c;NFC 碰一碰发视频这一应用场景&#xff0c;为用户带来了新颖且高效的视频分享体验。想象一下&#x…

C++从入门到入土(八)——多态的原理

目录 前言 多态的原理 动态绑定与静态绑定 虚函数表 小结 前言 在前面的文章中&#xff0c;我们介绍了C三大特性之一的多态&#xff0c;我们主要介绍了多态的构成条件&#xff0c;但是对于多态的原理我们探讨的是不够深入的&#xff0c;下面这这一篇文章&#xff0c;我们将…

Linux目录理解

前言 最近在复习linux&#xff0c;发现有些目录总是忘记内容&#xff0c;发现有些还是得从原义和实际例子去理解会记忆深刻些。以下是个人的一些理解 Linux目录 常见的Linux下的目录如下&#xff1a; 1. 根目录 / (Root Directory) 英文含义&#xff1a;/ 是文件系统的根…

c++领域展开第十七幕——STL(vector容器的模拟实现以及迭代器失效问题)超详细!!!!

文章目录 前言vector——基本模型vector——迭代器模拟实现vector——容量函数以及push_back、pop_backvector——默认成员函数vector——运算符重载vector——插入和删除函数vector——实现过程的问题迭代器失效memcpy的浅拷贝问题 总结 前言 上篇博客我们已经详细介绍了vecto…

植物知识分享论坛毕设

1.这四个文件直接是什么关系&#xff1f;各自都是什么作用&#xff1f;他们之间是如何联系的&#xff1f; 关系与联系 UserController.java 负责接收外部请求&#xff0c;调用 UserService.java 里的方法来处理业务&#xff0c; 而 UserService.java 又会调用 UserMapper.jav…

Business processes A bridge to SAP and a guide to SAP TS410 certification

Business processes A bridge to SAP and a guide to SAP TS410 certification

算法 之 ST表

文章目录 区间最大值 ST表(Sparse Table)是一种高效处理静态数据区间查询的数据结构&#xff0c;主要的作用是用于快速查询区间的最值&#xff0c;区间GCD,区间按位与或 在这里以区间最大值为例子说明st表的模版 总体的思想就是定义dp[i][j]表示下标为i长度为2^j的区间的最大值…

Deepseek X 文心智能体:谐音梗广告创意大师

体验链接 飞书文档 一、引言 在当今竞争激烈的市场环境下&#xff0c;广告创意对于产品或服务的推广至关重要。谐音广告以其独特的语言魅力&#xff0c;能够迅速吸引受众的注意力并留下深刻印象。本智能体旨在利用 DeepSeek 模型强大的语言分析和推理能力&#xff0c;为用户…

TCP简单链接的编程实现

TCP简单链接的编程实现 本文主要介绍TCP应用层的编码实现。 TCP是一种面向连接的、可靠的、基于字节流的传输层协议&#xff0c;它是互联网协议套件&#xff08;TCP/IP&#xff09;中的核心协议之一&#xff0c;广泛应用于需要可靠数据传输的场景&#xff0c;如&#xff1a;网…

【RHCE实验】搭建主从DNS、WEB等服务器

目录 需求 环境搭建 配置nfs服务器 配置web服务器 配置主从dns服务器 主dns服务器 从dns服务器 配置客户端 客户端测试 需求 客户端通过访问 www.nihao.com 后&#xff0c;能够通过 dns 域名解析&#xff0c;访问到 nginx 服务中由 nfs 共享的首页文件&#xff0c;内容…

【HarmonyOS Next之旅】DevEco Studio使用指南(三)

目录 1 -> 一体化工程迁移 1.1 -> 自动迁移 1.2 -> 手动迁移 1.2.1 -> API 10及以上历史工程迁移 1.2.2 -> API 9历史工程迁移 1 -> 一体化工程迁移 DevEco Studio从 NEXT Developer Beta1版本开始&#xff0c;提供开箱即用的开发体验&#xff0c;将SD…

nodejs使用 mysql2 模块获取 mysql 中的 json字段,而不是 mysql

mysql 模块获取的 json 字段&#xff0c;是字符串mysql2 模块获取的 json 字段&#xff0c;是符合预期的 json 对象 mysql mysql2 最后编辑于&#xff1a;2025-02-24 22:16:53 © 著作权归作者所有,转载或内容合作请联系作者 喜欢的朋友记得点赞、收藏、关注哦&#xff01;…

【网工第6版】第1章 计算机网络概论

目录 1计算机网络形成和发展 ■计算机网络 ■我国互联网发展 ■计算机网路分类 ■计算机网络应用 2 OSI和TCP/IP参考模型 ■网络分层的意义 ■OSI参考模型 ■TCP/IP参考模型 ■TCP/IP参考模型协议 3 数据封装与解封过程 ■封装 ■解封 1计算机网络形成和发展 ■计…

理解我们单片机拥有的资源

目录 为什么要查询单片机拥有的资源 所以&#xff0c;去哪些地方可以找数据手册 一个例子&#xff1a;STM32F103C8T6 前言 本文章隶属于项目&#xff1a; Charliechen114514/BetterATK: This is a repo that helps rewrite STM32 Common Repositorieshttps://github.com/C…

《我的Python觉醒之路》之转型Python(十五)——控制流

[今天是2025年3月17日&#xff0c;继续复习第一章节、第二章节的内容 ] 《我的Python觉醒之路》之转型Python&#xff08;十四&#xff09;——控制流

AndroidStudio+Android8.0下的Launcher3 导入,编译,烧录,调试

文章目录 编译完成搜索输出文件Android.mk配置gradle编译环境报错一报错二报错三输出文件下载INSTALL_FAILED_TEST_ONLY查找系统签名查找签名工具开始签名查看签名签名问题重新生成秘钥解决方案生成成功挽救错误:重新刷机更换testkey秘钥keystore生成keystoreINSTALL_FAILED_S…