From da78c7e1e83e7dc1c9378d57fcd9765b5f010559 Mon Sep 17 00:00:00 2001 From: zhangxuelin <959231531@qq.com> Date: Mon, 5 Aug 2024 09:47:33 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E7=94=BB=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/pdf/index copy.vue | 220 ++++++++++++++++++ src/renderer/src/components/pdf/index.vue | 170 +++++++++----- src/renderer/src/utils/pdfAndFabric copy.js | 133 +++++++++++ src/renderer/src/utils/pdfAndFabric.js | 142 ++++++----- 4 files changed, 535 insertions(+), 130 deletions(-) create mode 100644 src/renderer/src/components/pdf/index copy.vue create mode 100644 src/renderer/src/utils/pdfAndFabric copy.js diff --git a/src/renderer/src/components/pdf/index copy.vue b/src/renderer/src/components/pdf/index copy.vue new file mode 100644 index 0000000..ed14d19 --- /dev/null +++ b/src/renderer/src/components/pdf/index copy.vue @@ -0,0 +1,220 @@ + + + + + \ No newline at end of file diff --git a/src/renderer/src/components/pdf/index.vue b/src/renderer/src/components/pdf/index.vue index 276aa80..75a3bda 100644 --- a/src/renderer/src/components/pdf/index.vue +++ b/src/renderer/src/components/pdf/index.vue @@ -1,8 +1,17 @@ @@ -18,9 +27,10 @@ import { nextTick, defineEmits } from 'vue' -import { fabric } from 'fabric' +// import { fabric } from 'fabric' import { ElMessage } from 'element-plus' import { handleevent, savecanvsStore, initcanvasdata, displayData } from '@/utils/pdfAndFabric' +import {fabricVue, TYPES} from '@/plugins/fabric' const props = defineProps({ pdfObj: { @@ -39,6 +49,9 @@ const canvsStore = reactive({ }) const fabriccanvas = ref(null) const fabriccanvas1 = ref(null) + +const canvasFabricVue = ref(null) +const canvas1FabricVue = ref(null) // 页面总数 const numPagesTotal = ref(0) const imgarr = ref([]) @@ -61,6 +74,8 @@ const renderPage = async (canvasobj) => { canvasContext: canvasobj.context, viewport: viewport } + console.log(renderContext,22222222222222222222) + page.render(renderContext).promise.then((res) => { const img = document.createElement('img') img.src = canvasobj.canvas.toDataURL('image/png') @@ -71,35 +86,35 @@ const renderPage = async (canvasobj) => { // 根据传过来的pdf对象 判断改渲染哪一个fabric if (props.pdfObj.numberOfPdf == 2) { if (canvasobj.index == 0) { - - fabriccanvas.value.setWidth(screenWidth) - fabriccanvas.value.setHeight(screenHeight) - displayData(fabriccanvas, canvsStore, canvasobj, fabric, img) + canvasFabricVue.value.canvas.setWidth(screenWidth) + canvasFabricVue.value.canvas.setHeight(screenHeight) + // updateCanvasBackgroundImage(canvasFabricVue,img) + displayData(canvasFabricVue, canvsStore, canvasobj, fabric, img) } else { - fabriccanvas1.value.setWidth(screenWidth) - fabriccanvas1.value.setHeight(screenHeight) - displayData(fabriccanvas1, canvsStore, canvasobj, fabric, img) + canvas1FabricVue.value.canvas.setWidth(screenWidth) + canvas1FabricVue.value.canvas.setHeight(screenHeight) + displayData(canvas1FabricVue, canvsStore, canvasobj, fabric, img) + } } else { - fabriccanvas.value.setWidth(screenWidth) - fabriccanvas.value.setHeight(screenHeight) - displayData(fabriccanvas, canvsStore, canvasobj, fabric, img) + canvasFabricVue.value.canvas.setHeight(screenHeight) + displayData(canvasFabricVue, canvsStore, canvasobj, fabric, img) } - // console.log(imgarr.value) img.remove() } // 判断imgarr的JSONdata在canvsStore.pageArr有没有 - canvsStore.pageArr.forEach((item) => { - if (item.page == canvasobj.page) { - imgarr.value.forEach((img) => { - if (img.page == canvasobj.page) { - img.JSONdata = item.JSONdata - } - }) - } - }) + // canvsStore.pageArr.forEach((item) => { + // if (item.page == canvasobj.page) { + // imgarr.value.forEach((img) => { + // if (img.page == canvasobj.page) { + // img.JSONdata = item.JSONdata + // } + // }) + // } + // }) }) } + const updatePage = (canvasobj) => { renderPage(canvasobj) } @@ -108,16 +123,24 @@ const loadPdf = async (canvasobj) => { } const initPdf = async (type = 'default') => { + if(imgarr.value?.length){ + + } + imgarr.value.forEach(a=>{ + if(a.index==0){ + a.JSONdata=canvasFabricVue.value.canvas.toJSON() + }else{ + a.JSONdata=canvas1FabricVue.value.canvas.toJSON() + } + }) // 保存数据 savecanvsStore(imgarr, canvsStore) - // initcanvasdata(fabriccanvas) - // initcanvasdata(fabriccanvas1) - // 单页模式 - if (type == 'restone') { - // 清除 canvas 上的所有对象 - fabriccanvas1.value.clear() - // 释放 canvas 的资源 - fabriccanvas1.value.dispose() + + if(props.pdfObj.numberOfPdf == 1){ + canvasFabricVue.value.history.clean() + }else{ + canvasFabricVue.value.history.clean() + canvas1FabricVue.value.history.clean() } // 清除现有 canvas 元素的内容 canvasNumbsValue.value.forEach((canvasObj) => { @@ -149,7 +172,6 @@ const initPdf = async (type = 'default') => { } else { canvasNumbsValue.value[i].page = props.pdfObj.numPages + 1 } - canvasNumbsValue.value[i].index = i // 加载FabricVue await loadPdf(canvasNumbsValue.value[i]) @@ -158,43 +180,77 @@ const initPdf = async (type = 'default') => { } } const initPdfone = async () => { - setTimeout(() => { - fabriccanvas1.value = new fabric.Canvas('pdf-fabric1') - fabriccanvas1.value.isDrawingMode = true - fabriccanvas1.value.freeDrawingBrush.color = '#A33AFE' - fabriccanvas1.value.freeDrawingCursor = 'default' - fabriccanvas1.value.setWidth(595) - handleevent(fabriccanvas1.value, imgarr, 'two') - }, 0) - initPdf('addOnePage') + setTimeout( async() => { + const option = { freeDrawingCursor: 'default' } + const canvas2 = new fabricVue() + await canvas2.initCanvas(fabriccanvas1.value, option) + canvas2.canvas.setWidth(window.innerWidth/2-100) + canvas1FabricVue.value=canvas2 + await initPdf('addOnePage') + }, 0) + } onMounted(async () => { try { const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise numPagesTotal.value = pdf.numPages - // console.log(pdf) // 初始化fabriccanvas - fabriccanvas.value = new fabric.Canvas('pdf-fabric') - fabriccanvas.value.setWidth(595) - fabriccanvas.value.isDrawingMode = true - fabriccanvas.value.freeDrawingBrush.color = '#A33AFE' - fabriccanvas.value.freeDrawingCursor = 'default' - - fabriccanvas1.value = new fabric.Canvas('pdf-fabric1') - fabriccanvas1.value.isDrawingMode = true - fabriccanvas1.value.freeDrawingBrush.color = '#A33AFE' - fabriccanvas1.value.freeDrawingCursor = 'default' - fabriccanvas1.value.setWidth(595) + const option = { freeDrawingCursor: 'default'} + const canvas1 = new fabricVue() + await canvas1.initCanvas(fabriccanvas.value, option) + canvas1.canvas.setWidth(window.innerWidth/2-100) + // canvas1.canvas.isDrawingMode=false + canvas1.canvas.selectable = false; + canvas1.canvas.evented = false; + canvasFabricVue.value=canvas1 + const canvas2 = new fabricVue() + await canvas2.initCanvas(fabriccanvas1.value, option) + canvas2.canvas.setWidth(window.innerWidth/2-100) + canvas2.canvas.isDrawingMode=false + canvas1FabricVue.value=canvas2 + window.test={canvas1,canvas2} emit('update:numPagesTotal', pdf.numPages) + initPdf() - } catch (error) { + }catch (error) { console.log(error) ElMessage.error('pdf文件错误') } // 监听2个canvas事件 - handleevent(fabriccanvas.value, imgarr) - handleevent(fabriccanvas1.value, imgarr, 'two') + // handleevent(fabriccanvas.value, imgarr) + // handleevent(fabriccanvas1.value, imgarr, 'two') + }) +const handleTouchStart = (e) => { + console.log(e) + +}; + +const handleTouchMove = (e) => { + console.log(e) +}; + +const handleTouchEnd = (e) => { + console.log(e) + +}; + +const handleMouseDown = (e) => { + // console.log(e) +}; + +const handleMouseMove = (e) => { + // console.log(e) + + +}; + +const handleMouseUp = (e) => { + // console.log(e) + + +}; + defineExpose({ initPdf, initPdfone diff --git a/src/renderer/src/utils/pdfAndFabric copy.js b/src/renderer/src/utils/pdfAndFabric copy.js new file mode 100644 index 0000000..5a914b6 --- /dev/null +++ b/src/renderer/src/utils/pdfAndFabric copy.js @@ -0,0 +1,133 @@ +// 所有事件 +export function handleevent(canvas, imgarr, type = 'defalut') { + // // 鼠标按下 + // canvas.on('mouse:down', function (e) {}) + // // // 监听鼠标移动事件 + // // canvas.on('mouse:move', (options) => { + // // console.log('Mouse move event:', options); + // // }); + + // // 监听鼠标释放事件 + // canvas.on('mouse:up', (options) => { + // //判断是点击的哪一个 + // if (type == 'defalut') { + // if (imgarr.value[0].index == 0) { + // imgarr.value[0].JSONdata = canvas.toJSON() + // } + // if (imgarr.value[1]?.index == 0) { + // imgarr.value[1].JSONdata = canvas.toJSON() + // } + // } else { + // if (imgarr.value[0].index == 1) { + // imgarr.value[0].JSONdata = canvas.toJSON() + // } + // if (imgarr.value[1]?.index == 1) { + // imgarr.value[1].JSONdata = canvas.toJSON() + // } + // } + // console.log(imgarr.value) + + // }) +} +// 保存数据 +export function savecanvsStore(imgarr, canvsStore) { + // canvsStore.pageArr = mergeAndReplace(canvsStore.pageArr, imgarr.value) +} +// 重显数据 +export function displayData(canvas, canvsStore, canvasobj, fabric, img) { + // // 初始化 + // if (!canvsStore.pageArr.length) { + // fabric.Image.fromURL(img.src, (img) => { + // img.set({ + // left: 0, + // top: 0, + // scaleX: canvas.value.width / img.width, + // scaleY: canvas.value.height / img.height + // }) + // canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value)) + // }) + // return + // } + // canvsStore.pageArr.forEach((item) => { + // //初始化 + // if (item.page == canvasobj.page) { + // // canvas.value.clear() // 清除 Canvas + // // console.log(item.JSONdata, '找到一样的数据') + // canvas.value.loadFromJSON(item.JSONdata, () => { + // // 在所有对象加载完成后重新渲染画布 + // canvas.value.renderAll.bind(canvas.value) + // canvas.value.renderAll() + // // requestAnimationFrame(() => { + // // // 渲染所有对象 + + // // }) + // }) + // } else { + // // 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘 + // // // 清除 Canvas + // canvas.value.clear() + // requestAnimationFrame(function () { + // fabric.Image.fromURL(img.src, (img) => { + // img.set({ + // left: 0, + // top: 0, + // scaleX: canvas.value.width / img.width, + // scaleY: canvas.value.height / img.height + // }) + // canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value)) + // }) + // // 渲染所有对象 + // canvas.value.renderAll.bind(canvas.value) + // canvas.value.renderAll() + // }) + // } + // }) +} + +//page 一样替换 +const mergeAndReplace = (arr1, arr2) => { + // // 用于存储替换后的数组 + // const resultArray = array1.map(item1 => { + // // 在 array2 中查找 page 相同的对象 + // const replacement = array2.find(item2 => item2.page == item1.page); + // // 如果找到替换对象,则返回替换对象,否则返回原对象 + // return replacement ? replacement : item1; + // }); + + // // 将 array2 中 page 不在 array1 中的对象追加到结果数组中 + // array2.forEach(item2 => { + // const existsInArray1 = array1.some(item1 => item1.page == item2.page); + // if (!existsInArray1) { + // resultArray.push(item2); + // } + // }); + + // return resultArray; + + // 创建一个映射,将 arr2 中的对象按 page 属性存储 + let map = new Map(arr2.map((item) => [item.page, item])) + + // 使用 map 替换 arr1 中相应 page 的对象,并添加 arr2 中的对象 + arr1 = arr1.map((item) => (map.has(item.page) ? map.get(item.page) : item)) + + // 将 map 中存在但 arr1 中不存在的对象添加到 arr1 + for (let [page, obj] of map) { + if (!arr1.some((item) => item.page === page)) { + arr1.push(obj) + } + } + return arr1 +} + +// 初始化数据 +export function initcanvasdata(canvas) { + canvas.value.clear() // 清除 Canvas + // 设置画布的背景色或其他属性 + canvas.value.backgroundColor = 'rgba(255, 255, 255, 1)' // 白色背景 + + // 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘 + requestAnimationFrame(function () { + // 渲染所有对象 + canvas.value.renderAll.bind(canvas.value) + }) +} diff --git a/src/renderer/src/utils/pdfAndFabric.js b/src/renderer/src/utils/pdfAndFabric.js index 3807034..0cd4a55 100644 --- a/src/renderer/src/utils/pdfAndFabric.js +++ b/src/renderer/src/utils/pdfAndFabric.js @@ -1,84 +1,96 @@ // 所有事件 export function handleevent(canvas, imgarr, type = 'defalut') { - // 鼠标按下 - canvas.on('mouse:down', function (e) {}) - // // 监听鼠标移动事件 - // canvas.on('mouse:move', (options) => { - // console.log('Mouse move event:', options); - // }); + // // 鼠标按下 + // canvas.on('mouse:down', function (e) {}) + // // // 监听鼠标移动事件 + // // canvas.on('mouse:move', (options) => { + // // console.log('Mouse move event:', options); + // // }); - // 监听鼠标释放事件 - canvas.on('mouse:up', (options) => { - //判断是点击的哪一个 - if (type == 'defalut') { - if (imgarr.value[0].index == 0) { - imgarr.value[0].JSONdata = canvas.toJSON() - } - if (imgarr.value[1]?.index == 0) { - imgarr.value[1].JSONdata = canvas.toJSON() - } - } else { - if (imgarr.value[0].index == 1) { - imgarr.value[0].JSONdata = canvas.toJSON() - } - if (imgarr.value[1]?.index == 1) { - imgarr.value[1].JSONdata = canvas.toJSON() - } - } - console.log(imgarr.value) + // // 监听鼠标释放事件 + // canvas.on('mouse:up', (options) => { + // //判断是点击的哪一个 + // if (type == 'defalut') { + // if (imgarr.value[0].index == 0) { + // imgarr.value[0].JSONdata = canvas.toJSON() + // } + // if (imgarr.value[1]?.index == 0) { + // imgarr.value[1].JSONdata = canvas.toJSON() + // } + // } else { + // if (imgarr.value[0].index == 1) { + // imgarr.value[0].JSONdata = canvas.toJSON() + // } + // if (imgarr.value[1]?.index == 1) { + // imgarr.value[1].JSONdata = canvas.toJSON() + // } + // } + // console.log(imgarr.value) - }) + // }) } // 保存数据 export function savecanvsStore(imgarr, canvsStore) { canvsStore.pageArr = mergeAndReplace(canvsStore.pageArr, imgarr.value) } // 重显数据 -export function displayData(canvas, canvsStore, canvasobj, fabric, img) { +export function displayData(FabricVue, canvsStore, canvasobj, fabric, img) { // 初始化 + const canvas = FabricVue.value.canvas + if (!canvas) { + return + } + if (!canvsStore.pageArr.length) { - fabric.Image.fromURL(img.src, (img) => { - img.set({ - left: 0, - top: 0, - scaleX: canvas.value.width / img.width, - scaleY: canvas.value.height / img.height - }) - canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value)) - }) + fabric.Image.fromURL( + img.src, + (image) => { + image.set({ + left: 0, + top: 0, + scaleX: canvas.width / img.width, + scaleY: canvas.height / img.height + }) + // FabricVue.setBackgroundImage(image, FabricVue.renderAll.bind(FabricVue)) + // setBackgroundImage(image,FabricVue) + canvas.setBackgroundImage(image, () => { + FabricVue.value.render() + }) + }, + {crossOrigin: 'anonymous'} + ) return } canvsStore.pageArr.forEach((item) => { //初始化 if (item.page == canvasobj.page) { - // canvas.value.clear() // 清除 Canvas - // console.log(item.JSONdata, '找到一样的数据') - canvas.value.loadFromJSON(item.JSONdata, () => { + canvas.loadFromJSON(item.JSONdata, () => { // 在所有对象加载完成后重新渲染画布 - canvas.value.renderAll.bind(canvas.value) - canvas.value.renderAll() - // requestAnimationFrame(() => { - // // 渲染所有对象 - - // }) + // Utils.handleCanvasJSONLoaded(canvas) + canvas.requestRenderAll() // 批量重绘 }) } else { // 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘 // // 清除 Canvas - canvas.value.clear() + // canvas.clear() requestAnimationFrame(function () { - fabric.Image.fromURL(img.src, (img) => { - img.set({ - left: 0, - top: 0, - scaleX: canvas.value.width / img.width, - scaleY: canvas.value.height / img.height - }) - canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value)) - }) + fabric.Image.fromURL( + img.src, + (image) => { + image.set({ + left: 0, + top: 0, + scaleX: canvas.width / img.width, + scaleY: canvas.height / img.height + }) + canvas.setBackgroundImage(image, () => { + FabricVue.value.render() + }) + }, + {crossOrigin: 'anonymous'} + ) // 渲染所有对象 - canvas.value.renderAll.bind(canvas.value) - canvas.value.renderAll() + canvas.requestRenderAll() // 批量重绘 }) } }) @@ -86,23 +98,7 @@ export function displayData(canvas, canvsStore, canvasobj, fabric, img) { //page 一样替换 const mergeAndReplace = (arr1, arr2) => { - // // 用于存储替换后的数组 - // const resultArray = array1.map(item1 => { - // // 在 array2 中查找 page 相同的对象 - // const replacement = array2.find(item2 => item2.page == item1.page); - // // 如果找到替换对象,则返回替换对象,否则返回原对象 - // return replacement ? replacement : item1; - // }); - // // 将 array2 中 page 不在 array1 中的对象追加到结果数组中 - // array2.forEach(item2 => { - // const existsInArray1 = array1.some(item1 => item1.page == item2.page); - // if (!existsInArray1) { - // resultArray.push(item2); - // } - // }); - - // return resultArray; // 创建一个映射,将 arr2 中的对象按 page 属性存储 let map = new Map(arr2.map((item) => [item.page, item])) -- 2.44.0.windows.1 From 2a670c14476742e345c694b2a35c8183e040e4ce Mon Sep 17 00:00:00 2001 From: zhangxuelin <959231531@qq.com> Date: Tue, 6 Aug 2024 14:07:02 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/src/api/eTextbook/index.js | 35 ++++ src/renderer/src/components/pdf/index.vue | 169 ++++++++++++------- src/renderer/src/plugins/fabric/index.js | 1 + src/renderer/src/utils/pdfAndFabric.js | 113 +++++++++++-- src/renderer/src/views/classBegins/index.vue | 40 ++++- src/renderer/src/views/prepare/index.vue | 3 +- 6 files changed, 279 insertions(+), 82 deletions(-) create mode 100644 src/renderer/src/api/eTextbook/index.js diff --git a/src/renderer/src/api/eTextbook/index.js b/src/renderer/src/api/eTextbook/index.js new file mode 100644 index 0000000..c84df47 --- /dev/null +++ b/src/renderer/src/api/eTextbook/index.js @@ -0,0 +1,35 @@ +import request from '@/utils/request' + +// 新增pdf圈点勾画 +export const addsmartBookMark = (params) => { + return request({ + url: '/smarttalk/bookMark/addSmartBookMark', + method: 'post', + data:params + }) +} + +// 修改pdf圈点勾画 +export const updateSmartBookMarkContent = (params) => { + return request({ + url: '/smarttalk/bookMark/updateSmartBookMarkContent', + method: 'post', + data:params + }) +} + +// 根据书id获取pdf圈点勾画 +export const getBookMarkById = (bookId) => { + return request({ + url: '/smarttalk/bookMark/' + bookId, + method: 'get' + }) +} + +//根据id删除对应页数 +export function deleteBookMark(ids) { + return request({ + url: '/smarttalk/bookMark/' + ids, + method: 'delete' + }) +} diff --git a/src/renderer/src/components/pdf/index.vue b/src/renderer/src/components/pdf/index.vue index 75a3bda..63bd932 100644 --- a/src/renderer/src/components/pdf/index.vue +++ b/src/renderer/src/components/pdf/index.vue @@ -1,16 +1,17 @@ -