управление результатом двух eventlistener

#javascript

#javascript

Вопрос:

Я пытаюсь вернуть выбранное значение в выпадающем списке и приписать его atom.name для того, чтобы изменить имя атома. По умолчанию присутствует молекула ch2, а при нажатии на Na. Ch2 следует заменить на Na, но проблема заключается в области прослушивателя событий и возможности управлять этими двумя eventlistener. Тот, кто управляет выпадающим результатом

 var a = document.getElementById('atomDropdown');
a.addEventListener('change', function() {
  console.log(this.value);
}, false);
  

консоль.журнал выдает здесь правильный результат и
eventlistener, который управляет положением выпадающего меню с

 document.body.addEventListener('mouseup', e => {
    let atom = atoms.find(a => distance(a.position, { x: e.pageX, y: e.pageY}) <= a.r)
    atomDropdown.classList.remove('hidden')
    if(atom){
       atomDropdown.style.left = atom.position.x   'px'
       atomDropdown.style.top = (atom.position.y   atom.r)   'px'
    }
    console.log(atom.name);
})
  

Что я безуспешно пытаюсь сделать, так это приписать atom.name до этого значения.

 const canvas = document.createElement('canvas'),
	 context = canvas.getContext('2d'),
	 width = canvas.width = window.innerWidth,
	 height = canvas.height = window.innerHeight,
	 atoms = [],
	 bonds = [],
	 atomDropdown = document.getElementById('atomDropdown')

document.body.appendChild(canvas)

class Atom {
	constructor({ x, y, name }){
		this.position = {}
		this.position.x = x
		this.position.y = y
		this.name = name
		this.r = name.length * 10

		atoms.push(this)
	}

	draw(){
		let { position, name, r } = this,
		    { x, y } = position

		context.fillStyle = '#EEEEEE'
		context.beginPath()
		context.arc(x, y, r, 0, 2 * Math.PI)
		context.fill()


		context.fillStyle = '#000000'
		context.font = '20px sans-serif'
		context.textAlign = 'center'
		context.fillText(name, x, y   5)
	}
}

class Bond {
	constructor({ atom1, atom2, type }){
		this.atom1 = atom1
		this.atom2 = atom2
		
		bonds.push(this)
	}
	
	draw(){
		let { atom1, atom2 } = this
		
		context.beginPath()
		context.strokeStyle = '#000000'
		context.moveTo(atom1.position.x, atom1.position.y)
		context.lineTo(atom2.position.x, atom2.position.y)
		context.stroke()
	}
}

let hexagon = {
	size: 100,
	x: width/2,
	y: height/2
}

let lastAtom

for (var side = 0; side < 7; side  ) {
	let newAtom = new Atom({
		x: hexagon.x   hexagon.size * Math.cos(side * 2 * Math.PI / 6),
		y: hexagon.y   hexagon.size * Math.sin(side * 2 * Math.PI / 6),
		name: 'CH2'
	})
	
	if(lastAtom) new Bond({ atom1: lastAtom, atom2: newAtom })
	if(side == 6) new Bond({ atom1: newAtom, atom2: atoms[0] })
	lastAtom = newAtom
}

function render(){
	context.fillStyle = '#FFFFFF'
	context.fillRect(0,0,width,height)

	bonds.map(b => b.draw())
	atoms.map(a => a.draw())
}

render()

function distance(p1, p2){
	return Math.sqrt(Math.pow(p1.x - p2.x, 2)   Math.pow(p1.y - p2.y, 2))
}
var a = document.getElementById('atomDropdown');
a.addEventListener('change', function() {
  console.log(this.value);
}, false);

document.body.addEventListener('mouseup', e => {
	let atom = atoms.find(a => distance(a.position, { x: e.pageX, y: e.pageY}) <= a.r)
	atomDropdown.classList.remove('hidden')
	if(atom){
	   atomDropdown.style.left = atom.position.x   'px'
	   atomDropdown.style.top = (atom.position.y   atom.r)   'px'
	}
	console.log(atom.name);
})  
 #atomDropdown {
	position: absolute;
	
	amp;.hidden {
		display: none;
	}
}  
 <select id="atomDropdown" class="hidden">
	<option>Test1</option>
	<option>Test2</option>
	<option>Test3</option>
</select>  

Ответ №1:

Похоже, желаемое поведение заключается в изменении значения atom.name для атома, на который был сделан щелчок, замените его именем из выпадающего меню.

Например, щелкните по атому CH2 -> выберите «Test1» из выпадающего меню -> значение this.name для атома, который вы нажимаете, изменяется с «CH2» на «Test1».

Если это так, проблема заключается в том, как настроить таргетинг на тот же атом из вашего последнего события «наведения курсора мыши» в обработчике «изменить» для atomDropdown. В этом случае вы можете добавить новую переменную в свои определения:

 const canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight,
atoms = [],
bonds = [],
atomDropdown = document.getElementById('atomDropdown')

var selectedAtom = null
  

установите selectedAtom в экземпляр atom в обработчике «mouseup»:

 document.body.addEventListener('mouseup', e => {
let atom = atoms.find(a => distance(a.position, { x: e.pageX, y: e.pageY}) <= a.r)
atomDropdown.classList.remove('hidden')
if(atom){
   selectedAtom = atom
   atomDropdown.style.left = atom.position.x   'px'
   atomDropdown.style.top = (atom.position.y   atom.r)   'px'
}
console.log(atom.name);
  

})

и обновление selectedAtom.name в «событии изменения»:

 var a = document.getElementById('atomDropdown');
a.addEventListener('change', function() {
  if (selectedAtom) {
    selectedAtom.name = this.value;
    render(); //added so that the GUI updates when the name value changes
  }
  console.log(this.value);
}, false);
  

РЕДАКТИРОВАТЬ: чтобы немедленно обновить имя atom в том виде, в каком оно отображается в графическом интерфейсе / на дисплее, вам также необходимо вызвать render() после selectedAtom.name изменяется в событии «изменить» atomDropDown.

Комментарии:

1. Привет, esopp, это странно, потому что я могу изменить каждый атом, кроме правильного: codepen.io/anon/pen/WmdWbW

2. Похоже, что справа есть два перекрывающихся атома (т. Е. дополнительный, 7-й атом, нарисованный поверх первого в той же позиции). Если вы измените условие «сторона < 7» на «сторона < 6» в for (var side = 0; side < 7; side ) и «если (сторона == 6)» на «если (сторона ==5)» в if(side == 6) new Bond({ atom1: newAtom, atom2: atoms[0] }) , это устранит проблему.

3. Это случай, когда find() возвращает только первый совпадающий элемент в массиве, когда есть два совпадающих элемента. Это происходит в событии «наведение курсора мыши», где atoms[0] становится выбранным атомом. Поскольку атомы[0] будут отрисованы первыми в функции render(), при отрисовке атомов[6] атомы[0] закрываются.

Ответ №2:

Если я правильно понимаю этот вопрос, вы хотите установить значение выпадающего меню равным atom.name ?

Если это так, вам нужно добавить атрибут «value» к параметрам, тогда вы можете сказать что-то вроде:

 document.getElementById("atomDropdown").value = atom.name
  

HTML-код будет выглядеть примерно так:

 <select id="atomDropdown" class="hidden">
    <option value="Na">Test1</option>
    <option value="Ch2">Test2</option>
    <option value="O2">Test3</option>
</select>