当前位置: 首页 > news >正文

优惠券网站怎么做网站开发小组总结报告

优惠券网站怎么做,网站开发小组总结报告,网页视频下载浏览器,如何将自己做的网站推广出去文章目录 概要效果技术细节代码 概要 Canvas上面提供输入: 一、最简单可能是用dom渲染一个input,覆盖在图形上面进行文本编辑,编辑完再把内容更新到图形.这样简单,但是缺点也明显,就是它不是真正绘制在canvas上面,没…

文章目录

    • 概要
    • 效果
    • 技术细节
    • 代码

概要

Canvas上面提供输入:

一、最简单可能是用dom渲染一个input,覆盖在图形上面进行文本编辑,编辑完再把内容更新到图形.这样简单,但是缺点也明显,就是它不是真正绘制在canvas上面,没有层级。体验感较差

Fabric框架的思路大概是这样的。

二、如果要用自己是完全实现:键盘响应、撤消/重做、文本样式/布局、光标/选中区。那也有点难度。

三、还有一种就是利用contentEditable和textarea元素,在这些元素上面进行一些事件监听和文本内容处理。最重要的是保证canvas的字体样式要与元素的字体样式一样,这样才能利用textarea的兴标和选中区体系。不然的话就自己完完全全实现。

我下面实现纯canvas绘制的,就是利用textarea的键盘响应和光标体系,包括选中块。大楖就是保证canvas与元素之间这种些重要属性,做好同步。

下面看一下效果,因为也是花了二三个小时,弄了一个比较简单的,输入选中,光标指定位置生入,性能也是可以,输入响应很快

效果

 

技术细节

技术细节有一个地方,我是这样做的。因为我也没有借鉴别人的,就昨天突然闲,随手写了一下。

就是文本选中高亮:检测到selectionStart和selectionEnd不相等的情况下,就证明是选中区。

选中区的文本颜色和背景要高亮,如果做文本计算的话,那有点麻烦,而且性能也不好/。

我是这样做的。

文本先以默认颜色绘制一遍,然后把选中区作为剪切区域。再清空剪切区域的旧文本。再以高亮的颜色背景文本,再绘制一遍。就行了,这样很简单,不需要做额外文本处理了.

其它的:像光标位置,做到以下几点:

输入时:保持textarea的光标位置与canvas的同步

单点canvas文本框的时候:做一下坐标计算,算出光标位置,然后同步给textarea元素。
选中时候也需要同步给textarea元素,并且textarea也要选中这个区域。这样保证选中区删除文本或插入文本,保持一致

代码

不用管 canvasShapeRender这wh ,这是之前写一个类似figma的渐变调节器,小小的封装了一下,没有别的功能

   var renderer = new CanvasShapeRender(container, {width: 500,height: 500,background: '#efefef'})renderer.add(new RichInputEditor({owner: renderer,x: 100,y: 100}))renderer.requestDraw()
  class RichInputEditor2 extends CanvasShape {constructor(opts = {}) {super({type: 'group',...opts})this.minWidth = Math.max(200, this.width)this.minHeight = Math.max(30, this.height)this.width = this.minWidththis.height = this.minHeightlet scope = this;this.selectionStart = 0this.selectionEnd = 0;this.curLine = 0;// 光标所在行this.curX = 0//  this.curX=0 // 光标x轴位置this.lineHeight = 20this._focus = false;// 光标x轴位置let getCursorX = () => {let texts = this.text.texts;if (this.curLine >= texts.length) {return 0}if (this.selectionStart === this.selectionEnd) {return this.text.getPositionFromOffsetAndLine(this.selectionStart,this.curLine)}return 0}let getCursorLine = () => {let line = this.text.getLineFromPosition(this.selectionStart)return line}let run = false;let updateCursor = () => {if (run) {return}run = true;Promise.resolve().then(() => {this.selectionStart = this._textarea.selectionStartthis.selectionEnd = this._textarea.selectionEndthis.width=this._textarea.scrollWidththis.height=this._textarea.scrollHeightthis.curLine = getCursorLine()this.curX = getCursorX()run = false})}let border = this.border = this.addShape({type: 'rect',x: 0,y: 0,fillStyle: '#fff',strokeStyle: '#000',cursor:'text',beforeUpdate() {// scope.width=Math.max(minWidth,text.getTextMaxWidth())this.width = scope.widththis.height = scope.height},mousedown(e) {let [x,y]=this.transformLocalCoord(e.downPoint.x, e.downPoint.y)this.__selectionStart=nullsetTimeout(() => {scope._textarea.focus()scope._focus = truelet selectionStart=scope.text.getSelectionFromPosition(x,y)scope.selectionStart=selectionStartscope.selectionEnd=selectionStartscope._textarea.selectionStart=selectionStartscope._textarea.selectionEnd=selectionStartthis._selectionStart=selectionStartupdateCursor()this.owner.requestDraw()})e.stop()},drag(e){if(this._selectionStart==null){return}let [x,y]=this.transformLocalCoord(e.point.x, e.point.y)let _selectionEnd=scope.text.getSelectionFromPosition(x,y)let _selectionStart=this._selectionStartlet selectionStart=Math.min(_selectionStart,_selectionEnd)let selectionEnd=Math.max(_selectionStart,_selectionEnd)console.log('scope.selectionStart',selectionStart,selectionEnd)scope.selectionStart=selectionStartscope.selectionEnd=selectionEndthis.owner.requestDraw()},mouseup(){if(scope.selectionStart!==scope.selectionEnd){scope._textarea.setSelectionRange(scope.selectionStart,scope.selectionEnd)}this.owner.requestDraw()}})let text = this.text = this.addShape({silent:true,type: "text",x: 2,// ignore:true,fillStyle: '#000',textBaseline: 'middle',font: 'normal normal normal normal 14px sans-serif',beforeUpdate() {//this.lineHeight=80this.textOffset=[0,scope.lineHeight * 0.6]},})let selectionArea=new CanvasShapePath2D({silent:true,visible:false,fillStyle:'#0000ff',beforeUpdate(){this.visible=scope.selectionStart!==scope.selectionEnd&&scope._focuslet points=text.getSelectAreaFromSelection(scope.selectionStart,scope.selectionEnd)console.log('selectionArea',this.visible)this.fromMultiPolygon(points)}})this.add(selectionArea)let lightText = this.addShape({type: "text",x: 2,silent:true,visible:false,clipClearCanvas:true,fillStyle: '#fff',textBaseline: 'middle',drawClip(ctx){if(this.clipPath){ctx.beginPath()ctx.clip(this.clipPath)ctx.fillStyle=selectionArea.fillStylectx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height)}},beforeUpdate() {this.font=text.font//this.lineHeight=80this.textOffset=[0,scope.lineHeight * 0.6]this.texts=text.textsthis.setFontProperties(text)if(selectionArea.visible){this.clipPath=selectionArea.path2dthis.visible=true;}else{this.clipPath=nulllightText.visible=false}// this.height=scope.height},})text.setTextContent('fdasfdsaffdsfadasfdafdas\nabcdefg')let cursor = this.cursor = this.addShape({type: "line",x0: 0,y0: 0,x0: 0,y1: 30,x: 2,strokeStyle: '#000',beforeUpdate() {this.visible=scope.selectionStart===scope.selectionEnd&&scope._focusthis.x = 2 + scope.curXthis.y = scope.curLine * scope.lineHeightthis.y1 = scope.lineHeightthis.lineHeight = scope.lineHeight},})this._textarea = document.createElement('textarea')this._textarea.style.position = 'absolute'this._textarea.style.top = '0px'this._textarea.style.left = '-1000px'this._textarea.style.boxSizing = 'border-box'this._textarea.style.width = this.width + 'px'this._textarea.style.height = this.height + 'px'this._textarea.style.userSelect='none'this._textarea.value=text.getTextContent()text.bindDomTextStyle(this._textarea)//   this._textarea.style.opacity=0this._textarea.addEventListener('input', (e) => {let texts = e.target.value.split(/\n/)this.text.setTextContent(texts)    updateCursor()this.owner.requestDraw()})document.body.appendChild(this._textarea)}ownerCreate() {this.owner.onMousedown = () => {if (this._focus) {this._focus = falsethis.owner.requestDraw()}}let loop = () => {if (this._focus) {//  this.syncTextareaToCanvas()this.cursor.ignore = !this.cursor.ignorethis.owner.requestDraw()}setTimeout(loop, 800)}loop()}}

http://www.yayakq.cn/news/371764/

相关文章:

  • 个人购物网站备案做网站代码难么
  • 中建招聘网站网站建设出现401
  • qq群网站推广哪个网站可以改字体
  • 网站建设的swot分析seo概念的理解
  • 苏州做i网站的免费h5旅游网站模板
  • 大型网站域名郑州做网站设计
  • 杭州建站价格天津市招投标信息网
  • 企业网站制作优化营销型网站四大元素
  • 南通网站的优化深圳网站排名优化公司
  • 宁波网站seo报价网站后台哪些功能需要前端配合
  • 德邦公司网站建设特点便宜的购物app
  • 电子商务网站建设与管理习题答案贵阳小程序开发软件公司
  • 上海php网站开发公司淘宝联盟网站建设不完整
  • 邯郸网站建设找谁互联网网站建设情况统计表
  • 吉林省城乡建设部网站网站如何搭建
  • 如何建立平台网站仿新浪全站网站源码
  • 免费自助建站系统网站建设中页面下载
  • 手机怎么防止网站跳转永嘉县住房和城乡规划建设局网站
  • 网站建设公司包括哪些内容一个网站有哪几种漏洞
  • 中信建设有限责任公司校招百度seo软件首选帝搜软件
  • 江苏聚峰建设集团网站网站域名 续费
  • 郑州专业的网站建设自然堂网站建设情况
  • 有好点的做网站的公司吗wordpress主题 加载许多js
  • 平台网站开发风险营销型网站定做
  • 西安 内部网站建设建设网站如入什么费
  • 中文网站建设代码搭建一个网站要多少
  • 聚美联盟网站怎么做门户网站建设技术要求
  • 股票网站模板 dedecms河北建设部网站
  • 网站实名认证在哪html5手机网站开发视频教程
  • 网站备案幕布拍照怎么创建万维网网站