```
<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>
```
- LOLKU
- 工具類
- form/formData
- form
- formData
- iframe
- 渲染數據,防止內存泄漏
- 獲取url(路由)參數
- 常用方法
- 失去焦點軟鍵盤頁面亂
- 判斷數據類型
- 瀏覽器全屏
- 動態插入css
- 隨機生成自定義長度位數數字
- 驗證判斷
- localStorage 封裝存儲
- 格式化日期
- 計算兩個時間差
- 去除空格
- 將駝峰命名轉換為連字符
- 獲取dom屬性
- 深拷貝
- class操作
- 判斷是否打開瀏覽器控制臺
- 全國城市地區代碼表
- canvas合成工具
- 去除emoji表情符號
- 比較兩個對象屬性和內容(值)一致
- 微信結束頁面事件
- 正則匹配url替換域名
- 字符串拼接(渲染dom后傳值)
- 判斷是否是正則
- 日歷算法
- json 工具
- 是否支持webp格式
- h5底部輸入框被鍵盤遮擋問題
- php
- php 二級域名管理
- 單個或者多個域名跨域
- file_get_contents 正確使用
- fromData請求無法攜帶cookie
- 簡單的加密文件傳輸
- css
- 1px
- 滾動
- ios點擊有顏色
- 文本溢出省略號
- css動畫抖動
- 文本換行與不換行
- 阻止旋轉屏幕時自動調整字體大小
- vue
- vscode 調試
- 新技術
- vue-router 4.0
- vue3
- 基礎
- 試驗
- javascript
- 上傳問題
- 文件選中過,第二次再次選中不觸發change事件
- 上傳oss
- 后臺
- linux搭建服務
- 需安裝
- nginx
- 安裝
- nginx http 配置二級域名
- nginx https 配置二級域名
- 防止暴力破解
- 阿里申請免費https
- git
- 快速安裝
- 配置項
- node
- 安裝
- pm2
- mysql
- 安裝
- 創建、切換、查詢數據庫
- 常用命令
- cmake 編譯器
- redis
- 軟件下載
- git
- 百度git 記住密碼
- 經驗
- 上傳
- 軟件
- vscode
- 推薦插件
- 應用開發
- nwjs
- 入門
- package.json
- vue、react、angular 跑nwjs
- 打包
- 監聽屏幕
- 運行另一個.exe文件
- node應用
- electron
- 資料
- 安裝
- 實戰
- 崩潰日志報告
- electron-forge
- 托盤閃爍
- 開機自動啟動
- 消息通知
- 禁止默認事件
- 保證只有一個實例
- 打包且美化安裝界面
- 創建cli
- 添加Github徽章
- 自動更新
- docsify
- Lowdb存儲數據
- 備份、恢復、導入、導出
- 深度鏈接(協議)喚起Electron應用
- 說明
- 加載擴展插件
- 證書
- Sketch 插件
- 工作
- 宣傳文章地址
- api
- tinypng
- npm 插件
- fs封裝:fs-jetpack
- 判斷是否npm或yarn運行
- 字符串或緩沖區的gzip壓縮大小
- 克隆并修改RegExp實例
- 反轉對象的鍵/值
- http路由find-my-way
- dragula 拖拽(拖放)
- svga
- npm 腳手架搭建
- 項目
- 小工具
- svg轉圖片
- 日歷