739 lines
23 KiB
Vue

<template>
<div class="row">
<div class="col-1"></div>
<div class="col-10 q-pt-md">
<div ref="div" style="width: 100%; background-color: #646464; height: 40vh">
<div style="position: absolute">
<Vue3DraggableResizable :class="[options_model == index ? 'action' : 'point']"
v-for="(item, index) in value_point.length" :initW="point.w" :adsorbParent="false" :initH="point.h" :resizable="false"
v-model:x="value_point[index].x" v-model:y="value_point[index].y" @activated="options_model = index"
@click="options_model = index" @dragging="dragStartHandle($event, index)">
<span>{{
index+ 1
}}</span>
</Vue3DraggableResizable>
</div>
</div>
</div>
</div>
<div>
<div class="row" v-show="ispad">
<div class="col-1"></div>
<div class="col-2 q-px-md" @mousewheel="details_selsect"> <q-select class="q-pt-md" :label="$t('point')" :dense="true" filled
v-model="options_model" @update:model-value="(val) => { options_model = val }" :options="options" emit-value
map-options /></div>
<div class="col-2 q-px-md" @mousewheel="details_selsect_val($event,'x')">
<q-input filled type="number" class="q-pt-md" :dense="true"
v-model="value[options_model].x" @click="()=>{url.indexOf('pad')!=-1?ipad_chang=true:''}" :readonly="url.indexOf('pad')!=-1" @update:model-value="chang(options_model, $event, 'h')" label="x"
lazy-rules >
</q-input>
</div>
<div class="col-2 q-px-md" @mousewheel="details_selsect_val($event,'y')"> <q-input filled type="number" class="q-pt-md" :dense="true"
v-model="value[options_model].y" @click="()=>{url.indexOf('pad')!=-1?ipad_chang=true:''}" :readonly="url.indexOf('pad')!=-1" @update:model-value="chang(options_model, $event, 'h')" label="y"
lazy-rules /></div>
<div class="q-pt-md col-2">
<q-btn color="white" @click="reset(options_model, true, 'h')" text-color="black" :label="$t('reset')" />
</div>
<div class="col-2 q-pt-md">
<div><q-btn color="white" @click="resetall" text-color="black" :label="$t('resetall')" /></div>
</div>
</div>
<div v-show="!ispad" style="display: flex;justify-content: space-around;">
<div class="q-px-md" @mousewheel="details_selsect"> <q-select class="q-pt-md" :label="$t('point')" :dense="true" filled
v-model="options_model" @update:model-value="(val) => { options_model = val }" :options="options" emit-value
map-options /></div>
<div class="q-px-md" @mousewheel="details_selsect_val($event,'x')">
<q-input filled type="number" class="q-pt-md" :dense="true"
v-model="value[options_model].x" @focus="input_x_focus=true" @blur="input_x_focus=false" @click="()=>{url.indexOf('pad')!=-1?ipad_chang=true:''}" :readonly="url.indexOf('pad')!=-1" @update:model-value="chang(options_model, $event, 'h')" label="x"
lazy-rules >
<template v-if="input_x_focus" v-slot:append>
<q-icon name="arrow_upward" @mousedown="mousedown('+','x')" @mouseup="mouseup" />
<q-icon name="arrow_downward" @mousedown="mousedown('-','x')" @mouseup="mouseup" />
</template>
</q-input>
</div>
<div class="q-px-md" @mousewheel="details_selsect_val($event,'y')"> <q-input filled type="number" class="q-pt-md" :dense="true"
v-model="value[options_model].y" @focus="input_y_focus=true" @blur="input_y_focus=false" @click="()=>{url.indexOf('pad')!=-1?ipad_chang=true:''}" :readonly="url.indexOf('pad')!=-1" @update:model-value="chang(options_model, $event, 'h')" label="y"
lazy-rules >
<template v-if="input_y_focus" v-slot:append>
<q-icon name="arrow_upward" @mousedown="mousedown('+','y')" @mouseup="mouseup" />
<q-icon name="arrow_downward" @mousedown="mousedown('-','y')" @mouseup="mouseup" />
</template>
</q-input>
</div>
<div class="q-pt-md">
<q-btn color="white" @click="reset(options_model, true, 'h')" text-color="black" :label="$t('reset')" />
</div>
<div class="q-pt-md">
<div><q-btn color="white" @click="resetall" text-color="black" :label="$t('resetall')" /></div>
</div>
</div>
</div>
<!-- </div> -->
<q-dialog v-model="ipad_chang">
<q-card style="width: 40vw; max-width: 80vw;">
<q-card-section>
<!-- <div class="text-h6">{{ $t('point') +(options_model+1 )}}</div> -->
<div class="row">
<div class="col-4"><q-select class="q-pt-md" :label="$t('point')" :dense="true" filled
v-model="options_model" @update:model-value="(val) => { options_model = val }" :options="options" emit-value
map-options /></div>
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<div class="row">
<div class="col-12" style="text-align: center;"><q-btn color="white" text-color="black" icon="keyboard_arrow_up" @touchstart="handlerTouchstart('y','+')" @touchend="handlerTouchend" /></div>
</div>
<div class="row">
<div class="col-6" style="text-align: center;"><q-btn color="white" text-color="black" icon="keyboard_arrow_left" @touchstart="handlerTouchstart('x','-')" @touchend="handlerTouchend" /></div>
<div class="col-6" style="text-align: center;"><q-btn color="white" text-color="black" icon="keyboard_arrow_right" @touchstart="handlerTouchstart('x','+')" @touchend="handlerTouchend" /></div>
</div>
<div class="row">
<div class="col-12" style="text-align: center;"><q-btn color="white" text-color="black" icon="keyboard_arrow_down" @touchstart="handlerTouchstart('y','-')" @touchend="handlerTouchend" /></div>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn flat :label="$t('close')" color="primary" @click="ipad_chang=false" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<style scoped>
.action {
background-color: rgb(27, 180, 111);
border-radius: 50%;
}
.point {
background-color: rgb(186, 245, 245);
border-radius: 50%;
}
</style>
<!-- 取消浏览器自带的input箭头 使用q-input的图标实现 -->
<style>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none !important;
margin: 0;
}
</style>
<script lang="ts">
import {
defineComponent,
onMounted,
ref,
computed,
watch,
nextTick,
onBeforeUnmount,
defineExpose,
toRefs,
inject
} from "vue";
import { useStore } from "src/store";
import { useI18n } from "vue-i18n";
import Vue3DraggableResizable from 'vue3-draggable-resizable'
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
import DensityCorrection from "src/entities/DensityCorrection";
import DensityCorrectionPoint from "src/entities/DensityCorrectionPoint";
import { config } from "process";
import { QSelect, QInput, QBtn } from "quasar";
import { div } from "zrender/lib/core/vector";
import GlobalData from "src/common/GlobalData";
export default defineComponent({
name: "ComponentDensityCorrection",
components: {
Vue3DraggableResizable
},
props: {
col: {
type: String,
},
row: {
type: String,
}
},
setup(props) {
const now_selsect_projector:any = inject<string>("now_selsect_projector");
let set = GlobalData.getInstance().getCurrentClient();
let $store = useStore();
let $t = useI18n();
const ste_status = ref(0);
let allconfig = JSON.parse($store.state.fusion_configuration);
/**
* 平板弹窗修改
*/
const ipad_chang=ref(false)
/**
* 当前url路径
*/
let url = window.location.href;
const configselsect = computed(() => {
return $store.state.selected_projector;
});
/**
* 用于计算当前投影仪的索引
*/
let serverconfig = JSON.parse($store.state.fusion_configuration);
const selectedprojector = computed(() => {
return (
$store.getters.GetTheCurrentlySelectedCamera[0] * serverconfig.col +
$store.getters.GetTheCurrentlySelectedCamera[1]
);
});
let config = JSON.parse($store.state.fusion_configuration).projectors[selectedprojector.value];
const value_point_amount = ref(5)
const deepcopy = (o1: any, o2: any) => {
for (let k in o2) {
if (typeof o2[k] === "object") {
o1[k] = {};
deepcopy(o1[k], o2[k]);
} else {
o1[k] = o2[k];
}
}
};
const use_server_config = () => {
value.value = []
value_point.value = []
for (let index = 0; index < config.point4.length; index++) {
let tmp: DensityCorrectionPoint = config.point4[index];
value.value.push(tmp)
let x_y = coordinate_transformation_value_to_xy(tmp.x, tmp.y)
let def_x_f = coordinate_transformation_value_to_xy(tmp.def_x, tmp.def_y)
let tmp_point: DensityCorrectionPoint = {
control_point: tmp.control_point,
x: x_y.x,
y: x_y.y,
def_x: def_x_f.x,
def_y: def_x_f.y
}
value_point.value.push(tmp_point)
}
}
const use_set_cache = () => {
if (set_cache.value[selectedprojector.value] != null) {
let tmp = JSON.parse(set_cache.value[selectedprojector.value]);
deepcopy(value.value, tmp.value)
deepcopy(value_point.value, tmp.value_point)
recalculate_coordinates()
}
}
const save_set_cache = () => {
let tmp = { value: value.value, value_point: value_point.value }
set_cache.value[selectedprojector.value] = JSON.stringify(tmp);
}
watch(
() => configselsect,
(newVal, oldVal) => {
let tmp = JSON.parse($store.state.fusion_configuration);
let fortmp = null;
let i;
for (i of tmp.projectors) {
if (
i.col === $store.getters.GetTheCurrentlySelectedCamera[1] &&
i.row === $store.getters.GetTheCurrentlySelectedCamera[0]
) {
fortmp = JSON.parse(JSON.stringify(i));
}
}
ste_status.value = 1;
config = JSON.parse(JSON.stringify(fortmp));
use_server_config();
use_set_cache();
setTimeout(() => {
ste_status.value = 0;
}, 100);
},
{ deep: true }
);
const set_cache: any = ref([]);
//值
let value = ref(<DensityCorrection[]>[]);
//位置
let value_point = ref(<DensityCorrectionPoint[]>[]);
/**
* 当前选中的点的索引
*/
const options_model = ref(0)
const div = ref();
const max = ref({ x: 0, y: 0 })
const point = ref({ w: 20, h: 20 })
watch(() => options_model, (newval, oldval) => {
set?.SetBlendingOption("blending_grids_select_point", `4:${options_model.value + 1}`)
}, { deep: true })
/**
* 分辨率和页面的比例
*/
let Proportion = ref({ x: 100, y: 1000 });
nextTick(() => {
max.value.x = div.value.offsetWidth
max.value.y = div.value.offsetHeight
})
const options = computed(() => {
let tmp = []
for (let index = 0; index < value_point.value.length; index++) {
tmp.push({
label: `${index + 1}`,
value: index,
})
}
return tmp
})
const chang_point_amount = (val: number) => {
start_point()
}
const dragStartHandle = ($event: any, index: number) => {
let obj_x = $event.x
let obj_y = $event.y
let tmp = coordinate_transformation_xy_to_value(obj_x, obj_y)
value.value[index].x = Math.round(tmp.x)
value.value[index].y = Math.round(tmp.y)
/**
* 判断摄像机
*/
if(now_selsect_projector?.value=='0-0'){
if(index==1||index==3){
value.value[index].x = Math.round(tmp.x)>allconfig.projector_width?allconfig.projector_width:Math.round(tmp.x)
}
}
if(now_selsect_projector?.value=='0-1'){
if(index==0||index==2){
value.value[index].x = Math.round(tmp.x)<0?0:Math.round(tmp.x)
}
}
send_value(index, value.value[index].x , value.value[index].y)
save_set_cache()
}
const chang = (index: number, $event: any, type: string) => {
index = Number(index)
if (now_selsect_projector?.value == '0-0'&&props.col=='2') {
if (index == 1 || index == 3) {
value.value[index].x > allconfig.projector_width ? value.value[index].x =allconfig.projector_width : value.value[index].x
}
}
if (now_selsect_projector?.value == '0-1'&&props.col=='2') {
if (index == 0 || index == 2) {
value.value[index].x < 0 ? value.value[index].x= 0 : value.value[index].x
}
}
let tmp = coordinate_transformation_value_to_xy(value.value[index].x, value.value[index].y)
value_point.value[index].y = Math.round(tmp.y)
value_point.value[index].x = Math.round(tmp.x)
send_value(index, Math.round(value.value[index].x), Math.round(value.value[index].y))
save_set_cache()
}
/**
* 将分辨率的坐标转换为 页面的坐标
* @param x x坐标
* @param y y坐标
*/
const coordinate_transformation_value_to_xy = (x: number, y: number): { x: number, y: number } => {
x = x / Proportion.value.x
y = (allconfig.projector_height - y) / Proportion.value.y
return { x, y }
}
/**
* 将页面的坐标转换为 分辨率的坐标
* @param x x坐标
* @param y y坐标
*/
const coordinate_transformation_xy_to_value = (x: number, y: number): { x: number, y: number } => {
x = (x + point.value.w / 14) * Proportion.value.x
// x = (x-point.value.w) * Proportion.value.x
y = (max.value.y - (y + point.value.h)) * Proportion.value.y
return { x, y }
}
const start_point = () => {
value.value = []
value_point.value = []
for (let index = 0; index < config.point4.length; index++) {
let tmp: DensityCorrectionPoint = config.point4[index];
value.value.push(tmp)
let x_y = coordinate_transformation_value_to_xy(tmp.x, tmp.y)
let def_x_f = coordinate_transformation_value_to_xy(tmp.def_x, tmp.def_y)
let tmp_point: DensityCorrectionPoint = {
control_point: tmp.control_point,
x: x_y.x,
y: x_y.y,
def_x: def_x_f.x,
def_y: def_x_f.y
}
value_point.value.push(tmp_point)
}
}
/**
* 创建空值 让dom先渲染
*/
const start = () => {
let tmp: DensityCorrectionPoint = { control_point: 0, x: 0, y: 0, def_x: 0, def_y: 0 };
value.value.push(tmp)
value_point.value.push(tmp)
}
start()
onMounted(() => {
Proportion.value.x = allconfig.projector_width / (div.value.offsetWidth - point.value.w)
Proportion.value.y = allconfig.projector_height / (div.value.offsetHeight - point.value.h)
set?.GetBlendingConfig("").then((res) => {
config=JSON.parse(res?.config??"").projectors[selectedprojector.value];
start_point()
//start()
use_server_config()
if (
sessionStorage.FourPointCalibration &&
sessionStorage.FourPointCalibration.length > 0
) {
set_cache.value = JSON.parse(sessionStorage.FourPointCalibration);
use_set_cache();
}})
keyDown()
window.onresize = () => {
return (() => {
if (div != null) {
recalculate_coordinates()
}
})();
};
})
onBeforeUnmount(() => {
sessionStorage.FourPointCalibration = JSON.stringify(set_cache.value);
});
const reset = (index: number, send: boolean, type: string) => {
value.value[index].x = value.value[index].def_x
value.value[index].y = value.value[index].def_y
chang(index, value.value[index].def_y, type)
save_set_cache()
}
const send_value = (index: number, x: number, y: number) => {
let row = $store.getters.GetTheCurrentlySelectedCamera[0]
let col = $store.getters.GetTheCurrentlySelectedCamera[1]
set?.setBlendingCorrection(row, col, 4, value_point.value.length, index + 1, Number(x), Number(y));
}
const resetall = () => {
for (let index = 0; index < value_point.value.length; index++) {
value.value[index].x = value.value[index].def_x
value.value[index].y = value.value[index].def_y
let tmp = coordinate_transformation_value_to_xy(value.value[index].x, value.value[index].y)
value_point.value[index].y = Math.round(tmp.y)
value_point.value[index].x = Math.round(tmp.x)
}
send_value(-2,0,0)
save_set_cache()
}
const recalculate_coordinates = () => {
try {
Proportion.value.x = allconfig.projector_width / (div.value.offsetWidth - point.value.w)
Proportion.value.y = allconfig.projector_height / (div.value.offsetHeight - point.value.h)
max.value.x = div.value.offsetWidth
max.value.y = div.value.offsetHeight
for (let index = 0; index < value.value.length; index++) {
let x_y = coordinate_transformation_value_to_xy(value.value[index].x, value.value[index].y)
let def_x_y = coordinate_transformation_value_to_xy(value.value[index].def_x, value.value[index].def_x)
value_point.value[index].x = x_y.x
value_point.value[index].y = x_y.y
value_point.value[index].def_x = def_x_y.x
value_point.value[index].def_y = def_x_y.y
}
} catch (error) {
}
}
/**
* 滚轮切换
* @param details
*/
const details_selsect=(details:any) => {
let spt=details.deltaY/100
if(spt>0){
if(options_model.value>=value_point.value.length-1){
options_model.value=0
}else{
options_model.value++
}
}else{
if(options_model.value<=1){
options_model.value=value_point.value.length-1
}else{
options_model.value--
}
}
}
/**
* 滚轮改变数据
*/
const details_selsect_val = (details: any, type: string) => {
let spt = details.deltaY / 100
switch (type) {
case 'x':
if (spt < 0) {
if(now_selsect_projector?.value=='0-0'&&props.col=='2'){
if(options_model.value==1||options_model.value==3){
value.value[options_model.value].x>allconfig.projector_width?value.value[options_model.value].x = allconfig.projector_width:value.value[options_model.value].x++
}else{
value.value[options_model.value].x++
}
}else{
value.value[options_model.value].x++
}
} else {
if(now_selsect_projector?.value=='0-1'&&props.col=='2'){
if(options_model.value==0||options_model.value==2){
value.value[options_model.value].x <0?value.value[options_model.value].x = 0:value.value[options_model.value].x --
}else{
value.value[options_model.value].x--
}
}else{
value.value[options_model.value].x --
}
}
break;
default:
if (spt < 0) {
value.value[options_model.value].y++
} else {
value.value[options_model.value].y--
}
break;
}
chang(options_model.value,"","")
}
/**
* 长按实现
* 单击实现
*/
let loop: NodeJS.Timeout
let loop_end: NodeJS.Timeout
const handlerTouchstart=(type:string,fun:string)=>{
loop_end = setTimeout(() => {
loop=setInterval(()=>{
if(type=='x'){
if(fun=='+'){
value.value[options_model.value].x++
}else{
value.value[options_model.value].x--
}
}else{
if(fun=='+'){
value.value[options_model.value].y++
}else{
value.value[options_model.value].y--
}
}
chang(options_model.value,0,'')
},10)
}, 1000);
if(type=='x'){
if(fun=='+'){
value.value[options_model.value].x++
}else{
value.value[options_model.value].x--
}
}else{
if(fun=='+'){
value.value[options_model.value].y++
}else{
value.value[options_model.value].y--
}
}
chang(options_model.value,0,'')
}
const handlerTouchend=()=>{
clearTimeout(loop_end)
clearInterval(loop)
}
/**
* 键盘监听
*/
const keyDown = () => {
document.onkeydown = (e) => {
let lock=0;
let e1 = e || window.event || arguments.callee.caller.arguments[0]
switch (e.code) {
case "KeyW":
value.value[options_model.value].y++
break;
case "KeyA":
value.value[options_model.value].x--
break;
case "KeyS":
value.value[options_model.value].y--
break;
case "KeyD":
value.value[options_model.value].x++
break;
default:
lock=1
break;
}
if(lock==0)chang(options_model.value,"h", 'h')
}
}
const ispad=computed(()=>{
let url = window.location.href;
return url.indexOf("pad")!=-1
})
const add_cut=(fun:string,type:string)=>{
switch (type) {
case 'x':
if(fun=='+'){
value.value[options_model.value].x++
}else{
value.value[options_model.value].x--
}
break;
default:
if(fun=='+'){
value.value[options_model.value].y++
}else{
value.value[options_model.value].y--
}
break;
}
}
let loop_start:NodeJS.Timeout
let loop_finish:NodeJS.Timeout
const input_x_focus=ref(false)
const input_y_focus=ref(false)
const mousedown = (fun:string,type:string) => {
loop_start= setTimeout(() => {
loop_finish=setInterval(()=>{
switch (type) {
case 'x':
if(fun=='+'){
value.value[options_model.value].x++
}else{
value.value[options_model.value].x--
}
break;
default:
if(fun=='+'){
value.value[options_model.value].y++
}else{
value.value[options_model.value].y--
}
break;
}
chang(options_model.value,0,'')
},30)
}, 1000);
switch (type) {
case 'x':
if(fun=='+'){
value.value[options_model.value].x++
}else{
value.value[options_model.value].x--
}
break;
default:
if(fun=='+'){
value.value[options_model.value].y++
}else{
value.value[options_model.value].y--
}
break;
}
chang(options_model.value,0,'')
}
const mouseup = () => {
clearTimeout(loop_start)
clearInterval(loop_finish)
}
defineExpose({
options_model,
});
return {
input_x_focus,
input_y_focus,
mousedown,
mouseup,
add_cut,
now_selsect_projector,
details_selsect,
resetall,
div,
max,
point,
options_model,
value,
value_point,
dragStartHandle,
chang,
reset,
value_point_amount,
chang_point_amount,
options,
details_selsect_val,
ipad_chang,
url,
handlerTouchstart,
handlerTouchend,
ispad
}
}
})
</script>