Compare commits
4 Commits
19901d802f
...
a6fff59601
Author | SHA1 | Date |
---|---|---|
zhangxuelin | a6fff59601 | |
zhangxuelin | 2a670c1447 | |
zhangxuelin | 1d4cad94c1 | |
zhangxuelin | da78c7e1e8 |
|
@ -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'
|
||||
})
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
<template>
|
||||
<div class="canvasitem">
|
||||
<div class="pdfAdnFabric" id="pdfAdnFabric">
|
||||
<canvas id="pdf-fabric"></canvas>
|
||||
<canvas id="pdf-fabric1" v-if="props.pdfObj.numberOfPdf == 2"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup >
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
watch,
|
||||
reactive,
|
||||
defineProps,
|
||||
defineExpose,
|
||||
nextTick,
|
||||
defineEmits
|
||||
} from 'vue'
|
||||
import { fabric } from 'fabric'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { handleevent, savecanvsStore, initcanvasdata, displayData } from '@/utils/pdfAndFabric'
|
||||
|
||||
const props = defineProps({
|
||||
pdfObj: {
|
||||
type: Object,
|
||||
default: {
|
||||
numberOfPdf: 2, //pdf数量 只有 1 2
|
||||
pdfUrl: null,
|
||||
numPages: 1
|
||||
}
|
||||
}
|
||||
})
|
||||
// canvas的所有数据
|
||||
const canvsStore = reactive({
|
||||
id: 'xxxx',
|
||||
pageArr: []
|
||||
})
|
||||
const fabriccanvas = ref(null)
|
||||
const fabriccanvas1 = ref(null)
|
||||
// 页面总数
|
||||
const numPagesTotal = ref(0)
|
||||
const imgarr = ref([])
|
||||
// 多个pdf的对象
|
||||
const canvasNumbsValue = ref([])
|
||||
const emit = defineEmits(['update:numPagesTotal'])
|
||||
const renderPage = async (canvasobj) => {
|
||||
if (canvasobj.page > numPagesTotal.value) return
|
||||
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
||||
// 渲染当前页
|
||||
const page = await pdf.getPage(canvasobj.page)
|
||||
var screenWidth = window.innerWidth/2-100;
|
||||
var screenHeight = window.innerHeight;
|
||||
const viewport = page.getViewport({ scale:2})
|
||||
|
||||
const canvasElement = canvasobj.canvas
|
||||
canvasElement.width = viewport.width
|
||||
canvasElement.height = viewport.height
|
||||
const renderContext = {
|
||||
canvasContext: canvasobj.context,
|
||||
viewport: viewport
|
||||
}
|
||||
page.render(renderContext).promise.then((res) => {
|
||||
const img = document.createElement('img')
|
||||
img.src = canvasobj.canvas.toDataURL('image/png')
|
||||
canvasobj.canvas.remove()
|
||||
imgarr.value.push({ src: img.src, page: canvasobj.page, JSONdata: {}, index: canvasobj.index })
|
||||
img.onload = () => {
|
||||
// 在这里执行图像加载完成后的操作
|
||||
// 根据传过来的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)
|
||||
} else {
|
||||
fabriccanvas1.value.setWidth(screenWidth)
|
||||
fabriccanvas1.value.setHeight(screenHeight)
|
||||
displayData(fabriccanvas1, canvsStore, canvasobj, fabric, img)
|
||||
}
|
||||
} else {
|
||||
fabriccanvas.value.setWidth(screenWidth)
|
||||
fabriccanvas.value.setHeight(screenHeight)
|
||||
displayData(fabriccanvas, 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
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const updatePage = (canvasobj) => {
|
||||
renderPage(canvasobj)
|
||||
}
|
||||
const loadPdf = async (canvasobj) => {
|
||||
updatePage(canvasobj)
|
||||
}
|
||||
|
||||
const initPdf = async (type = 'default') => {
|
||||
// 保存数据
|
||||
savecanvsStore(imgarr, canvsStore)
|
||||
// initcanvasdata(fabriccanvas)
|
||||
// initcanvasdata(fabriccanvas1)
|
||||
// 单页模式
|
||||
if (type == 'restone') {
|
||||
// 清除 canvas 上的所有对象
|
||||
fabriccanvas1.value.clear()
|
||||
// 释放 canvas 的资源
|
||||
fabriccanvas1.value.dispose()
|
||||
}
|
||||
// 清除现有 canvas 元素的内容
|
||||
canvasNumbsValue.value.forEach((canvasObj) => {
|
||||
const context = canvasObj.context
|
||||
context.clearRect(0, 0, canvasObj.canvas.width, canvasObj.canvas.height)
|
||||
})
|
||||
// 清除所有对象
|
||||
imgarr.value = []
|
||||
canvasNumbsValue.value = []
|
||||
if (props.pdfObj.pdfUrl) {
|
||||
await nextTick() // 确保 DOM 渲染完成
|
||||
if (props.pdfObj.numberOfPdf == 1) {
|
||||
canvasNumbsValue.value = [{}]
|
||||
const canvasElement = document.createElement('canvas')
|
||||
canvasNumbsValue.value[0].canvas = canvasElement
|
||||
canvasNumbsValue.value[0].context = canvasNumbsValue.value[0].canvas.getContext('2d')
|
||||
canvasNumbsValue.value[0].page = props.pdfObj.numPages
|
||||
canvasNumbsValue.value[0].index = 0
|
||||
await loadPdf(canvasNumbsValue.value[0])
|
||||
} else {
|
||||
for (var i = 0; i < props.pdfObj.numberOfPdf; i++) {
|
||||
canvasNumbsValue.value[i] = {}
|
||||
const canvasElement = document.createElement('canvas')
|
||||
canvasNumbsValue.value[i].canvas = canvasElement
|
||||
canvasNumbsValue.value[i].context = canvasNumbsValue.value[i].canvas.getContext('2d')
|
||||
// 设置页数
|
||||
if (i == 0) {
|
||||
canvasNumbsValue.value[i].page = props.pdfObj.numPages
|
||||
} else {
|
||||
canvasNumbsValue.value[i].page = props.pdfObj.numPages + 1
|
||||
}
|
||||
|
||||
canvasNumbsValue.value[i].index = i
|
||||
// 加载FabricVue
|
||||
await loadPdf(canvasNumbsValue.value[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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(860)
|
||||
handleevent(fabriccanvas1.value, imgarr, 'two')
|
||||
}, 0)
|
||||
initPdf('addOnePage')
|
||||
}
|
||||
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(860)
|
||||
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(860)
|
||||
emit('update:numPagesTotal', pdf.numPages)
|
||||
initPdf()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
ElMessage.error('pdf文件错误')
|
||||
}
|
||||
// 监听2个canvas事件
|
||||
handleevent(fabriccanvas.value, imgarr)
|
||||
handleevent(fabriccanvas1.value, imgarr, 'two')
|
||||
})
|
||||
defineExpose({
|
||||
initPdf,
|
||||
initPdfone
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.canvasitem {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
.pdfAdnFabric {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
align-items: center;
|
||||
:deep(> div:nth-of-type(1)) {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,8 +1,18 @@
|
|||
<template>
|
||||
pdfAdnFabric<template>
|
||||
<div class="canvasitem">
|
||||
<div class="pdfAdnFabric" id="pdfAdnFabric">
|
||||
<canvas id="pdf-fabric"></canvas>
|
||||
<canvas id="pdf-fabric1" v-if="props.pdfObj.numberOfPdf == 2"></canvas>
|
||||
<div class="pdfAdnFabric" id="pdfAdnFabric" @touchstart="handleTouchStart">
|
||||
<!-- @touchmove="handleTouchMove"
|
||||
@touchend="handleTouchEnd"
|
||||
@mousedown="handleMouseDown"
|
||||
@mousemove="handleMouseMove"
|
||||
@mouseup="handleMouseUp" -->
|
||||
<div :class="ispointer ? 'ispointer' : ''">
|
||||
<canvas ref="fabriccanvas" />
|
||||
</div>
|
||||
<!-- style="pointer-events: none;" -->
|
||||
<div v-if="props.pdfObj.numberOfPdf === 2" :class="ispointer ? 'ispointer' : ''">
|
||||
<canvas ref="fabriccanvas1" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -18,10 +28,11 @@ 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'
|
||||
import { updateSmartBookMarkContent, addsmartBookMark,getBookMarkById } from '@/api/eTextbook/index'
|
||||
const props = defineProps({
|
||||
pdfObj: {
|
||||
type: Object,
|
||||
|
@ -32,13 +43,16 @@ const props = defineProps({
|
|||
}
|
||||
}
|
||||
})
|
||||
const ispointer = ref(false) //是否画笔模式
|
||||
// canvas的所有数据
|
||||
const canvsStore = reactive({
|
||||
id: 'xxxx',
|
||||
pageArr: []
|
||||
})
|
||||
const fabriccanvas = ref(null)
|
||||
const fabriccanvas1 = ref(null)
|
||||
|
||||
const canvasFabricVue = ref(null)
|
||||
const canvas1FabricVue = ref(null)
|
||||
// 页面总数
|
||||
const numPagesTotal = ref(0)
|
||||
const imgarr = ref([])
|
||||
|
@ -50,9 +64,9 @@ const renderPage = async (canvasobj) => {
|
|||
const pdf = await pdfjsLib.getDocument(props.pdfObj.pdfUrl).promise
|
||||
// 渲染当前页
|
||||
const page = await pdf.getPage(canvasobj.page)
|
||||
var screenWidth = window.innerWidth/2-100;
|
||||
var screenHeight = window.innerHeight;
|
||||
const viewport = page.getViewport({ scale:2})
|
||||
var screenWidth = window.innerWidth / 2 - 100
|
||||
var screenHeight = window.innerHeight
|
||||
const viewport = page.getViewport({ scale: 2 })
|
||||
|
||||
const canvasElement = canvasobj.canvas
|
||||
canvasElement.width = viewport.width
|
||||
|
@ -61,6 +75,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 +87,34 @@ 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,54 @@ const loadPdf = async (canvasobj) => {
|
|||
}
|
||||
|
||||
const initPdf = async (type = 'default') => {
|
||||
imgarr.value.forEach((a) => {
|
||||
if (a.index == 0) {
|
||||
a.JSONdata = canvasFabricVue.value.canvas.toJSON()
|
||||
} else {
|
||||
a.JSONdata = canvas1FabricVue.value.canvas.toJSON()
|
||||
}
|
||||
})
|
||||
if (type != 'default') {
|
||||
const nameMap = new Map(canvsStore.pageArr.map((item) => [item.page, item.id]))
|
||||
// 创建一个用于存储所有异步操作的数组
|
||||
let promises = []
|
||||
imgarr.value.forEach((item) => {
|
||||
if (nameMap.has(item.page)) {
|
||||
const params = {
|
||||
id: nameMap.get(item.page),
|
||||
contentData: JSON.stringify(item.JSONdata.objects)
|
||||
}
|
||||
promises.push(updateSmartBookMarkContent([params]))
|
||||
} else {
|
||||
promises.push(addsmartBookMark({
|
||||
pageNum: item.page,
|
||||
contentData: JSON.stringify(item.JSONdata.objects),
|
||||
bookId: props.pdfObj.bookId,
|
||||
type: '教材',
|
||||
source: 'smarttalk'
|
||||
}))
|
||||
|
||||
}
|
||||
})
|
||||
Promise.all(promises).then(res=>{
|
||||
getBookMarkById(props.pdfObj.bookId).then(res=>{
|
||||
const pageArr=getUniqueArrayByLastOccurrence(res.data)
|
||||
canvsStore.pageArr=[]
|
||||
pageArr.forEach((a) => {
|
||||
canvsStore.pageArr.push({ page: a.pageNum, id: a.id, JSONdata: a.contentData })
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
// 保存数据
|
||||
savecanvsStore(imgarr, canvsStore)
|
||||
// initcanvasdata(fabriccanvas)
|
||||
// initcanvasdata(fabriccanvas1)
|
||||
// 单页模式
|
||||
if (type == 'restone') {
|
||||
// 清除 canvas 上的所有对象
|
||||
fabriccanvas1.value.clear()
|
||||
// 释放 canvas 的资源
|
||||
fabriccanvas1.value.dispose()
|
||||
// savecanvsStore(imgarr, canvsStore)
|
||||
|
||||
if (props.pdfObj.numberOfPdf == 1) {
|
||||
// imgarr.value[0]
|
||||
canvasFabricVue.value.history.clean()
|
||||
} else {
|
||||
canvasFabricVue.value.history.clean()
|
||||
canvas1FabricVue.value.history.clean()
|
||||
}
|
||||
// 清除现有 canvas 元素的内容
|
||||
canvasNumbsValue.value.forEach((canvasObj) => {
|
||||
|
@ -149,7 +202,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])
|
||||
|
@ -157,44 +209,92 @@ const initPdf = async (type = 'default') => {
|
|||
}
|
||||
}
|
||||
}
|
||||
//根据page去重
|
||||
const getUniqueArrayByLastOccurrence=(array)=> {
|
||||
const uniqueItems = array.reduce((acc, current) => {
|
||||
// 使用 Map 来跟踪最后一个出现的 pageNum 和它的对象
|
||||
acc.set(current.pageNum, current);
|
||||
return acc;
|
||||
}, new Map());
|
||||
|
||||
// 将 Map 的值转换回数组
|
||||
const resultArray = Array.from(uniqueItems.values());
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
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')
|
||||
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)
|
||||
initPdf('addOnePage')
|
||||
}
|
||||
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)
|
||||
// 初始化fabriccanvas
|
||||
const option = { freeDrawingCursor: 'default' }
|
||||
const canvas1 = new fabricVue()
|
||||
// canvas1.boardConfig.mode= TYPES.ActionMode.OTHER
|
||||
// canvas1.boardConfig.mode= TYPES.ActionMode.ERASE
|
||||
await canvas1.initCanvas(fabriccanvas.value, option)
|
||||
canvas1.canvas.setWidth(window.innerWidth / 2 - 100)
|
||||
// canvas1.canvas.isDrawingMode=false
|
||||
canvasFabricVue.value = canvas1
|
||||
const canvas2 = new fabricVue()
|
||||
canvas2.boardConfig.mode = TYPES.ActionMode.DRAW
|
||||
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()
|
||||
|
||||
if (props.pdfObj.allPageData.length) {
|
||||
props.pdfObj.allPageData.forEach((a) => {
|
||||
if (a.pageNum == 1 || a.pageNum == 2) {
|
||||
canvsStore.pageArr.push({ page: a.pageNum, id: a.id, JSONdata: a.contentData })
|
||||
}
|
||||
})
|
||||
}
|
||||
await initPdf()
|
||||
} 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
|
||||
|
@ -217,4 +317,7 @@ defineExpose({
|
|||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.ispointer {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
|
@ -1615,6 +1615,7 @@ export class fabricVue {
|
|||
break
|
||||
case TYPES.ActionMode.OTHER: // 其他(工具选择)
|
||||
this.canvas.isDrawingMode = false
|
||||
objectSet.selectable = false
|
||||
this.canvas.freeDrawingCursor = 'default'
|
||||
break
|
||||
default:
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
}
|
|
@ -1,108 +1,187 @@
|
|||
|
||||
// 所有事件
|
||||
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) {
|
||||
|
||||
// 初始化
|
||||
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))
|
||||
})
|
||||
const canvas = FabricVue.value.canvas
|
||||
if (!canvas) {
|
||||
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({
|
||||
if (!canvsStore.pageArr.length) {
|
||||
fabric.Image.fromURL(
|
||||
img.src,
|
||||
(image) => {
|
||||
image.set({
|
||||
left: 0,
|
||||
top: 0,
|
||||
scaleX: canvas.value.width / img.width,
|
||||
scaleY: canvas.value.height / img.height
|
||||
scaleX: canvas.width / img.width,
|
||||
scaleY: canvas.height / img.height,
|
||||
erasable: false // 不允许擦拭
|
||||
})
|
||||
canvas.value.setBackgroundImage(img, canvas.value.renderAll.bind(canvas.value))
|
||||
// FabricVue.setBackgroundImage(image, FabricVue.renderAll.bind(FabricVue))
|
||||
// setBackgroundImage(image,FabricVue)
|
||||
// canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||
|
||||
canvas.setBackgroundImage(image, () => {
|
||||
canvas.renderAll.bind(canvas)
|
||||
FabricVue.value.render()
|
||||
})
|
||||
},
|
||||
{crossOrigin: 'anonymous'}
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const isfind=findObjectByPage(canvsStore.pageArr,canvasobj.page)
|
||||
if(isfind){
|
||||
const canvdata={
|
||||
objects:JSON.parse(isfind.JSONdata),
|
||||
version: "5.3.0"
|
||||
}
|
||||
requestAnimationFrame(function () {
|
||||
canvas.loadFromJSON(canvdata, () => {
|
||||
// 在所有对象加载完成后重新渲染画布
|
||||
// Utils.handleCanvasJSONLoaded(canvas)
|
||||
canvas.requestRenderAll() // 批量重绘
|
||||
})
|
||||
fabric.Image.fromURL(
|
||||
img.src,
|
||||
(image) => {
|
||||
image.set({
|
||||
left: 0,
|
||||
top: 0,
|
||||
scaleX: canvas.width / img.width,
|
||||
scaleY: canvas.height / img.height,
|
||||
selectable: false,
|
||||
evented: false,
|
||||
erasable: false // 不允许擦拭
|
||||
})
|
||||
// canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||
canvas.setBackgroundImage(image, () => {
|
||||
canvas.renderAll.bind(canvas)
|
||||
FabricVue.value.render()
|
||||
})
|
||||
},
|
||||
{crossOrigin: 'anonymous'}
|
||||
)
|
||||
// 渲染所有对象
|
||||
canvas.value.renderAll.bind(canvas.value)
|
||||
canvas.value.renderAll()
|
||||
canvas.requestRenderAll() // 批量重绘
|
||||
})
|
||||
}else{
|
||||
// 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
||||
// // 清除 Canvas
|
||||
// canvas.clear()
|
||||
requestAnimationFrame(function () {
|
||||
fabric.Image.fromURL(
|
||||
img.src,
|
||||
(image) => {
|
||||
image.set({
|
||||
left: 0,
|
||||
top: 0,
|
||||
scaleX: canvas.width / img.width,
|
||||
scaleY: canvas.height / img.height,
|
||||
selectable: false,
|
||||
evented: false,
|
||||
erasable: false // 不允许擦拭
|
||||
})
|
||||
// canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||
canvas.setBackgroundImage(image, () => {
|
||||
canvas.renderAll.bind(canvas)
|
||||
FabricVue.value.render()
|
||||
})
|
||||
},
|
||||
{crossOrigin: 'anonymous'}
|
||||
)
|
||||
// 渲染所有对象
|
||||
canvas.requestRenderAll() // 批量重绘
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// canvsStore.pageArr.forEach((item) => {
|
||||
// //初始化
|
||||
// if (item.page == canvasobj.page) {
|
||||
// // item.JSONdata
|
||||
// canvas.loadFromJSON(JSON.parse(item.JSONdata), () => {
|
||||
// // 在所有对象加载完成后重新渲染画布
|
||||
// // Utils.handleCanvasJSONLoaded(canvas)
|
||||
// canvas.requestRenderAll() // 批量重绘
|
||||
// })
|
||||
// } else {
|
||||
|
||||
// // 使用 requestAnimationFrame 来更新画布,确保在下一帧进行重绘
|
||||
// // // 清除 Canvas
|
||||
// // canvas.clear()
|
||||
// requestAnimationFrame(function () {
|
||||
// fabric.Image.fromURL(
|
||||
// img.src,
|
||||
// (image) => {
|
||||
// image.set({
|
||||
// left: 0,
|
||||
// top: 0,
|
||||
// scaleX: canvas.width / img.width,
|
||||
// scaleY: canvas.height / img.height,
|
||||
// selectable: false,
|
||||
// evented: false,
|
||||
// erasable: false // 不允许擦拭
|
||||
// })
|
||||
// // canvas.setBackgroundImage(image, canvas.renderAll.bind(canvas));
|
||||
// canvas.setBackgroundImage(image, () => {
|
||||
// canvas.renderAll.bind(canvas)
|
||||
// FabricVue.value.render()
|
||||
// })
|
||||
// },
|
||||
// {crossOrigin: 'anonymous'}
|
||||
// )
|
||||
// // 渲染所有对象
|
||||
// canvas.requestRenderAll() // 批量重绘
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
}
|
||||
// 找到page一样的
|
||||
const findObjectByPage=(array, page)=> {
|
||||
const foundObject = array.find(obj => obj.page === page);
|
||||
return foundObject || false;
|
||||
}
|
||||
|
||||
//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]))
|
||||
|
|
|
@ -33,19 +33,26 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch, reactive } from 'vue'
|
||||
import { useRoute } from 'vue-router';
|
||||
import * as pdfjsLib from 'pdfjs-dist/legacy/build/pdf'
|
||||
import pdfCanvas from '@/components/pdf/index.vue'
|
||||
import { getStaticUrl } from '@/utils/tool'
|
||||
const { ipcRenderer } = require('electron')
|
||||
import { getBookMarkById } from '@/api/eTextbook/index'
|
||||
// const getStaticUrl=(url)=>{
|
||||
// return url
|
||||
// }
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = getStaticUrl('/lib/build/pdf.worker.mjs')
|
||||
|
||||
// 传过去的参数
|
||||
const pdfObj = reactive({
|
||||
numberOfPdf: 2, //显示几页
|
||||
pdfUrl: getStaticUrl('aaa.pdf', 'user', 'selfFile', true),
|
||||
allPageData:[],
|
||||
bookId:null,
|
||||
numPages: 1 //当前页数
|
||||
})
|
||||
|
||||
const textbookId=ref(null)
|
||||
// 总条数
|
||||
const numPagesTotal = ref(0)
|
||||
const pdfCanvaslist = ref(null)
|
||||
|
@ -60,7 +67,7 @@ const navtopage = (type) => {
|
|||
pdfObj.numPages += num
|
||||
}
|
||||
if (pdfObj.numPages > numPagesTotal.value) return
|
||||
pdfCanvaslist.value.initPdf()
|
||||
pdfCanvaslist.value.initPdf('rest')
|
||||
}
|
||||
// 最小化窗口
|
||||
const minimize = () => {
|
||||
|
@ -70,7 +77,7 @@ const handleUpdate = (data) => {
|
|||
numPagesTotal.value = data
|
||||
if (numPagesTotal.value == 1) {
|
||||
pdfObj.numberOfPdf = 1
|
||||
pdfCanvaslist.value.initPdf('restone')
|
||||
pdfCanvaslist.value.initPdf('rest')
|
||||
}
|
||||
}
|
||||
// 单双页切换
|
||||
|
@ -87,10 +94,33 @@ const switchPageMode = () => {
|
|||
} else {
|
||||
// 多页切单页
|
||||
pdfObj.numberOfPdf = 1
|
||||
pdfCanvaslist.value.initPdf('restone')
|
||||
pdfCanvaslist.value.initPdf('rest')
|
||||
}
|
||||
}
|
||||
onMounted(async () => {})
|
||||
onMounted(async () => {
|
||||
const route = useRoute();
|
||||
textbookId.value = route.query.textbookId
|
||||
pdfObj.bookId=textbookId.value
|
||||
getBookMarkById(textbookId.value).then(res=>{
|
||||
pdfObj.allPageData=getUniqueArrayByLastOccurrence(res.data)
|
||||
console.log(pdfObj.allPageData)
|
||||
})
|
||||
})
|
||||
|
||||
//根据page去重
|
||||
const getUniqueArrayByLastOccurrence=(array)=> {
|
||||
const uniqueItems = array.reduce((acc, current) => {
|
||||
// 使用 Map 来跟踪最后一个出现的 pageNum 和它的对象
|
||||
acc.set(current.pageNum, current);
|
||||
return acc;
|
||||
}, new Map());
|
||||
|
||||
// 将 Map 的值转换回数组
|
||||
const resultArray = Array.from(uniqueItems.values());
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -449,7 +449,8 @@ export default {
|
|||
|
||||
// 打开PDF-课件
|
||||
navtoPdf() {
|
||||
createWindow('open-PDF', { url: '/classBegins/index' })
|
||||
console.log(this.uploadData.textbookId)
|
||||
createWindow('open-PDF', { url: '/classBegins/index?textbookId='+this.uploadData.textbookId })
|
||||
},
|
||||
// 上课-工具类悬浮
|
||||
openLesson() {
|
||||
|
|
Loading…
Reference in New Issue