import util from '../../../../utils/util'
Component({
properties: {
questionSubject: {
type: Object,
},
},
observers: {
questionSubject({
content: {
connectingLineList, optionList }}) {
this.setData({
leftData: connectingLineList,
rightData: optionList
});
wx.nextTick(() => {
this.getCanvas()
})
},
context(val) {
val && this.displayData()
}
},
data: {
leftActive: -1,
rightActive: -1,
leftPoint: new Map(),
rightPoint: new Map(),
leftData: [],
rightData: [],
myAnswer: new Map(),
context: null,
canvasHeight: 0,
canvasWidth: 0,
width: 0,
height: 0,
top: 0,
},
methods: {
async displayData() {
let data = wx.getStorageSync('connectionAnswer')
if (data) {
const arr = data.filter(item => item[0] == this.data.questionSubject.questionTopicId)
if (arr.length === 0) return
const tempMap = new Map()
this.setData({
myAnswer: util.objToMap(arr[0][1], tempMap)
})
const list = this.data.questionSubject.answer.connectingLineList
const newTempMap = this.addColorToAnswerData(tempMap, list)
wx.nextTick(() => {
this.rePaint(newTempMap)
})
}
},
addColorToAnswerData(map, list) {
const newMap = new Map()
for (const [key, val] of map) {
val.forEach(id => {
const color = list.find(item => item.prefix == key).answerPrefix.includes(id) ? 'green' : 'red'
const oldVal = newMap.get(key)
oldVal ? newMap.set(key, [...oldVal, {
id, color }]) : newMap.set(key, [{
id, color }])
})
}
return newMap
},
handleBeSure() {
const id = this.data.questionSubject.questionTopicId
let data = wx.getStorageSync('connectionAnswer')
if (!data) {
data = []
} else {
const index = data.findIndex(item => item[0] == id)
index !== -1 && data.splice(index, 1)
}
let myAnswer = {
}
myAnswer = util.mapToObj(this.data.myAnswer, myAnswer)
data.push([id, myAnswer])
wx.setStorageSync('connectionAnswer', data)
this.triggerEvent('onSubmit')
},
itemClick(e) {
let {
isleft,
prefix,
} = e.target.dataset;
if (isleft) {
this.data.leftActive = prefix
} else {
this.data.rightActive = prefix
}
let leftActive = this.data.leftActive;
let rightActive = this.data.rightActive;
if ((leftActive !== -1) && (rightActive !== -1)) {
const source = this.data.leftPoint.get(leftActive);
const target = this.data.rightPoint.get(rightActive);
const myAnswer = this.data.myAnswer;
const existenceLeftActive = myAnswer.get(leftActive)
if (existenceLeftActive !== undefined) {
if (existenceLeftActive.filter(item => item == rightActive).length) {
myAnswer.set(leftActive, existenceLeftActive.filter(item => item != rightActive));
this.rePaint(this.data.myAnswer)
this.setData({
leftActive: -1,
rightActive: -1,
myAnswer
})
return;
}
existenceLeftActive.push(rightActive);
myAnswer.set(leftActive, existenceLeftActive)
} else {
myAnswer.set(leftActive, [rightActive])
}
const sy = source.y - this.data.top + (source.height / 2);
const ty = target.y - this.data.top + (target.height / 2);
const dpr = wx.getWindowInfo().pixelRatio;
this.lineTo({
x: 0,
y: sy * dpr
}, {
x: this.data.width * dpr,
y: ty * dpr
})
this.setData({
leftActive: -1,
rightActive: -1,
myAnswer
});
}
},
rePaint: function (myAnswer) {
const dpr = wx.getWindowInfo().pixelRatio;
const context = this.data.context;
context.clearRect(0, 0, this.data.width * dpr, this.data.height * dpr);
for (let [key, val] of myAnswer) {
val.forEach(point => {
const source = this.data.leftPoint.get(key);
const target = this.data.rightPoint.get(point.id ?? point);
const sy = source.y - this.data.top + (source.height / 2);
const ty = target.y - this.data.top + (target.height / 2);
this.lineTo({
x: 0,
y: sy * dpr
}, {
x: this.data.width * dpr,
y: ty * dpr
}, point.color ?? 'blue')
});
}
},
lineTo(source, target, color = 'blue') {
const context = this.data.context;
if (context) {
context.beginPath();
context.moveTo(source.x, source.y);
context.lineTo(target.x, target.y);
context.lineWidth = '3'
context.strokeStyle = color
context.stroke();
context.closePath();
}
},
getCanvas() {
this.setData({
canvasHeight: 0,
myAnswer: new Map()
})
const query = this.createSelectorQuery();
query.select('#matching-box').boundingClientRect();
query.exec((res) => {
const dpr = wx.getWindowInfo().pixelRatio
this.setData({
canvasWidth: res[0].width * dpr,
canvasHeight: res[0].height * dpr - 200
});
const width = res[0].width * dpr;
const leftPoint = new Map();
this.data.leftData.forEach(item => {
const query = this.createSelectorQuery();
query.select('#left' + item.prefix).boundingClientRect();
query.exec((res) => {
leftPoint.set(item.prefix, {
x: 0,
y: res[0].top,
height: res[0].height
})
});
})
const rightPoint = new Map();
this.data.rightData.forEach(item => {
const query = this.createSelectorQuery();
query.select('#right' + item.prefix).boundingClientRect();
query.exec((res) => {
rightPoint.set(item.prefix, {
x: width,
y: res[0].top,
height: res[0].height
})
});
})
this.setData({
rightPoint,
leftPoint
});
this.createSelectorQuery().select('#canvas')
.fields({
node: true,
size: true
})
.exec((res) => {
const {
node,
width,
height
} = res[0];
if (!node) return
const dpr = wx.getSystemInfoSync().pixelRatio;
node.width = res[0].width * dpr;
node.height = res[0].height * dpr;
const context = node.getContext('2d');
this.setData({
context,
width,
height
})
});
this.createSelectorQuery().select('#matching-box').boundingClientRect().exec((res) => {
const {
top
} = res[0];
this.setData({
top
})
})
});
},
父组件
formatConnectionQuestionAnswer(subject, list) {
list.connectingLineList.map(item => {
const {
content } = subject.content.connectingLineList.find(left => left.prefix === item.prefix)
item.formatPrefix = content
item.formatAnswerPrefix = []
item.answerPrefix.forEach(answerRight => {
const {
content } = subject.content.optionList.find(right => right.prefix === answerRight)
item.formatAnswerPrefix.push(content)
})
})
},
connectionQuestionSumbit() {
const {
questionMainId, questionTopicId, questionVodUserRecordId } = this.data.questionSubject
this.setData({
questionMainId,
questionTopicId,
questionVodUserRecordId
});
const connectionQuestionRef = this.selectComponent('#connection-question')
let submitAnswer = {
connectingLineList: [],
resourceList: null
}
const answer = connectionQuestionRef.data.myAnswer
for(const [key, value] of answer) {
submitAnswer.connectingLineList.push({
prefix: key,
answerPrefix: value,
})
}
this.questionVodUserSubmit(submitAnswer)
},
utils
function mapToObj(map, obj = {
}) {
for (const [key, value] of map) {
obj[key] = value
}
return obj
}
function objToMap(obj, map) {
for (const key in obj) {
map.set(key, obj[key])
}
return map
}