Wan_Backup / custom_nodes /ComfyUI-Easy-Use /ComfyUI-Easy-Use-Frontend /src /components /graph /sliderControl.vue
| <template lang="pug"> | |
| div(:class="prefix" :data-id="id") | |
| template(v-if="values?.length>0 && show") | |
| div(:class="[prefix + '-item',{'positive': index == 3 && type == 'sdxl' && mode == IPA_LAYER_WEIGHTS}, {'negative': index == 6 && type == 'sdxl' && mode == IPA_LAYER_WEIGHTS}]" v-for="(item,index) in values" :key="index") | |
| div(:class="prefix + '-item-input'") {{item.value}} | |
| div(:class="prefix + '-item-scroll'" ref="scroll") | |
| div(:class="prefix + '-item-bar'" ref="bar" :style="{'top':item.top || (100 - calculatePercent(item.default,item.min,item.max) + '%')}" ="e=>mousedown(e,item,index)" ="e=>dblclick(e,item,index)") | |
| div(:class="prefix + '-item-area'" :style="{'height':item.height || calculatePercent(item.default,item.min,item.max) + '%'}") | |
| div(:class="prefix + '-item-label'") | |
| span {{item.label}} | |
| </template> | |
| <script setup> | |
| import { $t } from '@/composable/i18n.js' | |
| import { ref, reactive, computed, watch, defineComponent, defineProps, defineEmits, onMounted } from 'vue' | |
| import cloneDeep from "lodash/cloneDeep"; | |
| const prefix = 'comfyui-easyuse-slider' | |
| defineComponent({name:prefix}) | |
| const IPA_LAYER_WEIGHTS = 'ipadapter layer weights' | |
| const props = defineProps({ | |
| id: { | |
| type: String | Number, | |
| default: '' | |
| }, | |
| mode:{ | |
| type: String, | |
| default: '' | |
| }, | |
| type:{ | |
| type: String, | |
| default: '' | |
| }, | |
| values:{ | |
| type: Array, | |
| default: [] | |
| }, | |
| show:{ | |
| type:Boolean, | |
| default:false | |
| } | |
| }) | |
| const emit = defineEmits(['changeValues','showSlider']) | |
| const calculatePercent = (value,min,max) => ((value - min) / (max - min) * 100) | |
| const getIPALayerDefaultValue = (length, i, v = undefined) => { | |
| switch (props.mode){ | |
| case IPA_LAYER_WEIGHTS: | |
| let default_values = {3:2.5,6:1} | |
| let value = default_values[i] || 0 | |
| return { | |
| default: length == 12 ? value : 0, | |
| min:-1, | |
| max:3, | |
| step:0.05, | |
| value: v!==undefined ? v : (length == 12 ? value : 0), | |
| top: v!==undefined ? (100 - calculatePercent(v,-1,3) + '%') : null, | |
| height: v!==undefined ? calculatePercent(v,-1,3) + '%' : null, | |
| } | |
| } | |
| } | |
| watch(_ => props.mode, async (newValue, oldValue) => { | |
| if(newValue!==oldValue){ | |
| switch (newValue) { | |
| case IPA_LAYER_WEIGHTS: | |
| if(!oldValue && props.values?.length > 0){ | |
| const array = props.values.map(item=>{ | |
| const v = item.split(':') | |
| return getIPALayerDefaultValue(props.values.length, v[0], parseFloat(v[1])) | |
| }) | |
| await emit('changeValues', array) | |
| }else{ | |
| let length = props.type == 'sd1' ? 16 : 12 | |
| let array = Array.from({length}, (v, i) => (getIPALayerDefaultValue(length, i))) | |
| await emit('changeValues', array) | |
| } | |
| break | |
| } | |
| } | |
| emit('showSlider') | |
| },{ | |
| immediate:true | |
| }) | |
| watch(_=> props.type, (newValue, oldValue) =>{ | |
| if(newValue == oldValue) return | |
| if(props.mode == IPA_LAYER_WEIGHTS){ | |
| let length = props.type == 'sd1' ? 16 : 12 | |
| let array = Array.from({length}, (v, i) => (getIPALayerDefaultValue(length, i))) | |
| emit('changeValues', array) | |
| } | |
| }) | |
| const scroll = ref(null) | |
| const bar = ref(null) | |
| const mousedown = (e, item, index)=>{ | |
| let event = e || window.event; | |
| let _scroll = scroll.value[index] | |
| let _bar = bar.value[index] | |
| let _values = cloneDeep(props.values) | |
| let y = event.clientY - _bar.offsetTop; | |
| document.onmousemove = (e) => { | |
| let event = e || window.event; | |
| let top = event.clientY - y; | |
| if(top < 0){ | |
| top = 0; | |
| } | |
| else if(top > _scroll.offsetHeight - _bar.offsetHeight){ | |
| top = _scroll.offsetHeight - _bar.offsetHeight; | |
| } | |
| // top到最近的GridHeight值 | |
| let GridTotal = (item.max - item.min) / item.step | |
| let GridHeight = (_scroll.offsetHeight - _bar.offsetHeight)/ GridTotal | |
| top = Math.round(top / GridHeight) * GridHeight; | |
| const _top = Math.floor(top/(_scroll.offsetHeight - _bar.offsetHeight)* 100) + '%'; | |
| const _height = Math.floor((_scroll.offsetHeight - _bar.offsetHeight - top)/(_scroll.offsetHeight - _bar.offsetHeight)* 100) + '%'; | |
| const _value = parseFloat(parseFloat(item.max - (item.max-item.min) * (top/(_scroll.offsetHeight - _bar.offsetHeight))).toFixed(2)) | |
| _values[index] = {..._values[index],...{ top:_top, height:_height, value:_value}} | |
| emit('changeValues', _values) | |
| window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); | |
| } | |
| } | |
| const dblclick = (e, item, index)=>{ | |
| let _values = cloneDeep(props.values) | |
| _values[index] = {..._values[index],...{ top:null, height:null, value:item.default}} | |
| emit('changeValues', _values) | |
| } | |
| onMounted(()=>{ | |
| document.onmouseup = _=> document.onmousemove = null; | |
| }) | |
| </script> |