🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
``` <template> <div > <!-- <a href="tel:13828172679">13622178579</a> --> <div class="msg" ref="msg" v-html="html"></div> <!-- 选择器 --> <div class="start" ref="start" :style="{left: startL,top: startT}"> <i class="line"></i> <div class="drag"></div> </div> <div class="end" ref="end" :style="{left: endL,top: endT}"> <i class="line"></i> <div class="drag"></div> </div> <div class="end"></div> <div class="mask" v-show="maskShow"> <div class="copy">复制</div> <div class="search">查询</div> <div class="error-recovery">纠错</div> </div> </div> </template> <script> // 长按事件、选择改变、如果长度为0,咱们就不用显示 import anime from 'animejs' export default { /* 注意:名称是以文件名命名,如果冲突请修改 */ name: 'demo', data () { return { maskShow: false, html: '', startT: '', startL: '', endL: '', endT: '' } }, computed: {}, created(){ this.$nextTick((e) => { // var text = '忽然想起那年夏日毕业之际,我送他的藏头巧妙情诗,还有在QQ的匿名坦白说,还有我第一次鼓起' var text = `《普通高中语文课程标准(2017年版)》提出了语文学科核心素养——“语言建构与运用”“思维发展与提升”“审美鉴赏与创造”“文化传承与理解”。语文学科核心素养是对“三维目标”的升华,集中体现了新时代人才所应具备的必备品格和关键能力,为语文教学革新指明了方向。阅读在语文教学中是一个不可或缺的板块,阅读教学在语文教学中具有举足轻重的作用。语文学科核心素养的提出对阅读教学提出了更高的要求,最突出的表现为注重思维品质在阅读教学中的提升。所谓“研究性阅读教学”强调的是研究特性,追求阅读的广度和深度,着眼于高阶思维品质的培育。结合自身实习学段——高中,本人旨在依据2017年新版高中语文课标对思维品质培育的要求,建立起“思维发展与提升”的学科核心素养与“语文研究性阅读教学”之间的理论契合点,结合思维发展的阶段理论,就语文研究性阅读教学理念发表自己的见解,并就语文研究性阅读教学策略提出自己的设想。除绪论和结语之外,正文共分为五个部分:第一部分:本人旨在从阅读教学入手,分析新课程背景下高中语文学科对于阅读能力的培养要求,对“语文研究性阅读教学”进行概念界定。同时,本人还将阐述推行语文研究性阅读教学的意义。第二部分:本人依据语文教育实际,总结分析语文阅读教学现状,指出现行阅读教学主要存在着深度缺乏、形式化倾向、思维培育不够等问题。同时,本人将概述课改先行区特级教师的一些成功做法,以供借鉴。第三部分:理念是实践的先导。本人旨在提出自己对语文研究性阅读教学理念的认识:增强问题研究能力,注重思维方式规训,推行深度阅读教学。第四部分:在上述理念的指导下,就高中语文研究性阅读教学策略提出自己的设想——任务驱动、专题研习、拓展迁移、批判反思。在此部分本人结合相关教学案例进行阐释分析,以支撑自己的论述。第五部分:指出践行语文研究性阅读教学的局限性,以及应该处理好的四对关系。` let str = '' for(var i=0;i < 100;i++) { var len = text.length; str += '<div class="list">' for(var k=0;k < len;k++) { str += '<span data-index="'+ k +'">' + text[k] + '</span>' } str += '</div>' } this.html = str /** * 1、长按的话,获取当前选中的文本对象 * 2、如果按到哪里的源为空,则全新当前这段,这段的第一个和最后一个选中 * 3、如果按到的是span标签的话, * 优化:长按后,获取下面整个dom节点,通过不移动到哪个位置,来定位 * 先查询当前选中了几个文本,然后在根据这些文本选中的索引来 * 限制拉出这个list宽度高度 * 复制、查询、弹窗位置,当在最顶上最侧边 */ var maxH = 0, // 滑到高度最大位置 maxW = 0, // 滑到宽度最大位置 mouseTime = 0, // 长按时间 listOfset = null, // 每列距离上面左边多少 listChildren = [], // 存储长按整段文字距离屏幕多少 selectTxtDom = [], // 选中的所以文本 allListChildrenDom = [], // 整个一段文本所有的dom flagDarg = false, // 拖拽开关 that = this; // 当前vue对象 var startIndex = 0, endIndex = 0, startDragIndex = 0 // 拖拽开始位置到某个地方停止了,进行标记在哪个位置上 // 滚动监听 let win = window let scrollY = win.screenY let maxTop = 0 let tParent = null; // 父节点 let timer2 = null; // win.addEventListener('scroll',(i) => { scrollY = win.scrollY if(tParent) { maxTop = tParent.parentNode.getBoundingClientRect().top } // 更新 listChildren 里面的数据 clearTimeout(timer2) timer2 = setTimeout(() => { let len = allListChildrenDom.length for(var i=0;i<len;i++) { listChildren[i] = allListChildrenDom[i].getBoundingClientRect() } }, 300); }) this.$nextTick(() => { var list = this.$refs.msg.querySelectorAll('.list'); let len = list.length; for(var i=0;i<len;i++) { list[i].ontouchstart = function () { mouseTime = new Date().getTime() } list[i].ontouchend = function (e) { if(new Date().getTime() - mouseTime >= 500) { // 长按了,如果是滚动的了话,证明不需要 // 清除之前选中的文本样式 let subLen = allListChildrenDom.length for(var k=0;k<subLen;k++) { allListChildrenDom[k].style.backgroundColor = '' allListChildrenDom[k].style.color = '' } // 存储下当前选中的这段文本文字距离屏幕多少 allListChildrenDom = this.children subLen = allListChildrenDom.length listChildren = [] for(var k=0;k < subLen;k++) { listChildren.push(allListChildrenDom[k].getBoundingClientRect()) } // 获取当前的 var domWrap = window.getComputedStyle(this) maxW = domWrap.width maxW = Number(maxW.slice(0,maxW.length-2)); maxH = domWrap.height maxH = Number(maxH.slice(0,maxH.length-2)); listOfset = this.getBoundingClientRect(); maxW = maxW + listOfset.left maxH = maxH + listOfset.top - that.$refs.start.offsetHeight + 5; console.log(maxW, maxH); selectTxtDom = [] selectTxtDom.push(e.target) if(e.target.nodeName === 'SPAN') { // 当前长按选择的dom对象,x轴与y轴 tParent = e.target var clientRect = tParent.getBoundingClientRect() startIndex = Number(e.target.dataset.index) // 获取当前选中的第几个dom // 当前文字结束位置与 endIndex = startIndex == allListChildrenDom.length-1 ? startIndex + 1 : startIndex // 获取当前选中的第几个dom that.startL = clientRect.left + 'px' that.startT = clientRect.top + scrollY + 'px' that.endL = clientRect.right + 'px' that.endT = clientRect.top + scrollY + 'px' e.target.style.backgroundColor = 'rgba(60,172,243,.4)' e.target.style.color = '#39789f' }else { // 空格或者是当前,选择全部的 } } } } }) // 开始位置拖拽 var endPostion = null; uDrags(this.$refs.start,{ dragStart:function (msg) { flagDarg = true endPostion = listChildren[endIndex] // console.log(listChildren,'listChildren'); }, dragging:function (msg) { /** * “开始位置”的x轴与y轴都得限制在“结束位置”x轴与y轴之间: * 1、每次都得检查y轴与x轴位置 * 2、当y轴在可行范围内则x轴就可以跑 * 3、当x轴在可行范围内则y轴就可以跑 */ if(msg.top + endPostion.height < endPostion.top) { that.startL = msg.left + 'px' if(msg.top > 0) { that.startT = msg.top + scrollY + 'px' } checkText(msg) }else if(msg.left < endPostion.left && msg.left > listOfset.left) { that.startL = msg.left + 'px' if(msg.top <= endPostion.top) { that.startT = msg.top + scrollY + 'px' } checkText(msg) } }, dragEnd:function (msg) { flagDarg = false // 松手后,将去除下 let postion = listChildren[startDragIndex] that.startT = postion.top + scrollY + 'px' that.startL = postion.left + 'px' } }) // 结束位置拖拽 var startIndex = null; uDrags(this.$refs.end,{ dragStart:function (msg) { console.log(listChildren,'listChildren'); }, dragging:function (msg) { // 不能超过选中的一段文本最左边距离与右边距离 if(msg.left < maxW && msg.left > listOfset.left) { // if() { // 不能超过开始位置 // } that.endL = msg.left + 'px' } // 不能超过选中的一段文本最上边距离与下边距离 if(msg.top > listOfset.top && msg.top < maxH) { that.endT = msg.top + 'px' } // }, dragEnd:function (msg) { } }) // 检测选中的某个部分文字 function checkText (msg) { /** * == 开始标记位置不能超过结束位置。如果是结束位置不能超过开始位置 == * 开始位置: * 开始位置的标记, */ // 限制结束区域 for(var i=0;i<startIndex;i++) { /** * 从开始值到结束值中间取dom * 1、得看top值与left值 */ if(listChildren[i].left >= msg.left && listChildren[i].top >= msg.top - listChildren[i].height) { // console.log(,'listChildren[i]'); startDragIndex = i; // 拖拽,选中的开始拖拽是这个地方 for(var s = 0;s<i;s++) { allListChildrenDom[s].style.backgroundColor = '' allListChildrenDom[s].style.color = '' } for(var k=i;k<endIndex;k++) { allListChildrenDom[k].style.backgroundColor = 'rgba(60,172,243,.4)' allListChildrenDom[k].style.color = '#39789f' } break; } } } // 拖拽 function uDrags (dom,cbJson) { var cbJson = cbJson || {} let msg = { dom:dom, dragging:false, isClick:false, startX:0, startY:0, domX:0, domY:0, left:0, top:0, x:0, y:0, dTop:0, // 直接可以使用 dLeft:0, isDOM : ( typeof HTMLElement === 'object' ) ? function(obj){ return obj instanceof HTMLElement; } : function(obj){ return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string'; }, getStyle:function (obj,attr){ return obj.currentStyle?obj.currentStyle:getComputedStyle(obj); } } var dTop ='',dLeft='' // instanceof HTMLElement 兼容性不好 if(!msg.isDOM(dom)) { return console.warn('err:错误,这个不是dom') } dom.addEventListener('touchstart', down) dom.addEventListener('mousedown',down) var windowFlags = false; function down (event) { windowFlags = false; event.preventDefault();// 阻止默认事件 if (event.type === 'touchstart') { event.clientY = event.touches[0].clientY; event.clientX = event.touches[0].clientX; } // 获取基本信息 msg.dragging = true; // 按下了 msg.isClick = true; // 在点击状态 msg.startX = event.clientX; // 获取浏览器左边缘鼠标位置 msg.startY = event.clientY; // 获取浏览器右边缘鼠标位置 msg.domX = msg.startX - dom.getBoundingClientRect().left; // dom的左边边缘与按下去鼠标的位置 msg.domY = msg.startY - dom.getBoundingClientRect().top; // dom的上边边缘与按下去鼠标的位置 var styles = msg.getStyle(msg.dom) dTop = parseFloat(styles.top); dLeft = parseFloat(styles.left); cbJson.dragStart(msg) // 并且添加事件 window.addEventListener('mousemove', onDragging); // 监听当前移动 window.addEventListener('touchmove', onDragging); // 监听当前移动 window.addEventListener('mouseup', onDragEnd); // 添加抬起事件 window.addEventListener('touchend', onDragEnd);// 添加抬起事件 window.addEventListener('contextmenu', onDragEnd); // 右击事件 if (self != top) { let subWin = window; // 解决嵌入到iframe中,滑动的太快,出去了,没有执行 dragEnd 回调 window.parent.addEventListener('mousemove', function (ev) { if (windowFlags) { return; } windowFlags = true; cbJson.dragEnd(msg); subWin.removeEventListener('mousemove', onDragging); subWin.removeEventListener('touchmove', onDragging); subWin.removeEventListener('mouseup', onDragEnd); subWin.removeEventListener('touchend', onDragEnd); subWin.removeEventListener('contextmenu', onDragEnd); ev.preventDefault(); }, false) } } // 监听拖着 function onDragging (event) { if (msg.dragging) { msg.isClick = false; if(event.type === 'touchmove') { event.clientY = event.touches[0].clientY; event.clientX = event.touches[0].clientX; } msg.x = event.clientX; msg.y = event.clientY; msg.left = msg.x - msg.domX; msg.top = msg.y - msg.domY; msg.dTop = dTop + msg.y - msg.startY; msg.dLeft = dLeft + msg.x - msg.startX; if(cbJson.dragging && typeof cbJson.dragging === 'function') { cbJson.dragging(msg) } } } // 监听拖拽放开 function onDragEnd (e) { if (msg.dragging) { /* * 防止在 mouseup 后立即触发 click,导致滑块有几率产生一小段位移 * 不使用 preventDefault 是因为 mouseup 和 click 没有注册在同一个 DOM 上 */ setTimeout(function (){ msg.dragging = false; if (!msg.isClick) { if(cbJson.dragEnd && typeof cbJson.dragEnd === 'function') { windowFlags = true cbJson.dragEnd(msg) // msg = null; } } }, 0); window.removeEventListener('mousemove', onDragging); window.removeEventListener('touchmove', onDragging); window.removeEventListener('mouseup', onDragEnd); window.removeEventListener('touchend', onDragEnd); window.removeEventListener('contextmenu', onDragEnd); } } // 取消事件 return function off (offDom) { if(Array.isArray(offDom)) { var len = offDom.length; for(var i=0;i<len;i++) { if(msg.isDOM(offDom[i])) { offDom[i].removeEventListener('mousedown',down) offDom[i].removeEventListener('touchstart',down) } } }else if(msg.isDOM(offDom)) { offDom.removeEventListener('mousedown',down) offDom.removeEventListener('touchstart',down) } } } // window.addEventListener('contextmenu', function(e){ // e.preventDefault(); // },false) // 取消之后右键就没有菜单了document.oncontextmenu = function(e){ document.oncontextmenu = function(e){ var event = e||window.event; event.stopPropagation() if(e.preventDefault){ e.preventDefault(); }else{ event.returnValue = false; } } // document.body.addEventListener('touchmove' , function(e){ //   var e=e||window.event; //   e.preventDefault(); // },{ passive: false }) var timer = null; var mask = document.querySelector('.mask'), that = this; document.onselectionchange = function(e) { let str = '' let select = window.getSelection() console.log(select,''); clearTimeout(timer) timer = setTimeout(() => { str = select.toString() that.maskShow = !!str },100) }; }) function selectText(element) { if (document.body.createTextRange) { let range = document.body.createTextRange(); range.moveToElementText(element); range.select(); } else if (window.getSelection) { let selection = window.getSelection(); let range = document.createRange(); range.selectNodeContents(element); selection.removeAllRanges(); selection.addRange(range); } else { alert('none'); } } }, methods: {} } </script> <style lang="scss" scoped> p { -webkit-touch-callout: none; } .mask { -moz-user-select: none; /*火狐*/ -webkit-user-select: none; /*webkit浏览器*/ -ms-user-select: none; /*IE10*/ -khtml-user-select: none; /*早期浏览器*/ user-select: none; width: 100%; height: 40px; background: aqua; position: fixed; left: 0; bottom: 0; display: flex; justify-content: space-between; } div { -moz-user-select: none; /*火狐*/ -webkit-user-select: none; /*webkit浏览器*/ -ms-user-select: none; /*IE10*/ -khtml-user-select: none; /*早期浏览器*/ } .msg { /deep/ .list { font-size: 1.5rem; margin: 1rem 0; } } .start,.end { position: absolute; left: 0; top: -222; } .start,.end { height: 2.5rem; .line { width: .1rem; height: 2.5rem; background-color: #3CACF3; display: block; } .drag { width: 1.4rem; height: 1.4rem; background: #3CACF3; position: absolute; top: 2rem; left: -.8rem; border-radius: 100%; } } // p { // // pointer-events: none; // -webkit-touch-callout: none; // } // * { // -webkit-touch-callout: none; // } </style> ```