init
This commit is contained in:
parent
06f61d8ce8
commit
f301cb744d
2271 changed files with 103162 additions and 0 deletions
|
@ -0,0 +1,41 @@
|
|||
# Мяч под курсор мыши
|
||||
|
||||
Основная сложность первого этапа -- сдвинуть мяч под курсор, т.к. координаты клика `e.clientX/Y` -- относительно окна, а мяч позиционирован абсолютно внутри поля, его координаты `left/top` нужно ставить относительно левого-верхнего внутреннего (внутри рамки!) угла поля.
|
||||
|
||||
Чтобы правильно вычислить координаты мяча, нужно получить координаты угла поля и вычесть их из `clientX/Y`:
|
||||
|
||||
```js
|
||||
var field = document.getElementById('field');
|
||||
var ball = document.getElementById('ball');
|
||||
|
||||
field.onclick = function(e) {
|
||||
|
||||
*!*
|
||||
var fieldCoords = field.getBoundingClientRect();
|
||||
var fieldInnerCoords = {
|
||||
top: fieldCoords.top + field.clientTop,
|
||||
left: fieldCoords.left + field.clientLeft
|
||||
};
|
||||
|
||||
ball.style.left = e.clientX - fieldInnerCoords.left + 'px';
|
||||
ball.style.top = e.clientY - fieldInnerCoords.top + 'px';
|
||||
*/!*
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
[iframe src="solution" height="260" link edit]
|
||||
|
||||
В примере выше фон мяча намеренно окрашен в серый цвет, чтобы было видно, что элемент позиционируется верно.
|
||||
|
||||
Попробуйте дальше сами.
|
||||
|
||||
# Дальнейшее решение
|
||||
|
||||
Мяч нужно сдвинуть на половину его ширины и высоты `ball.clientWidth/clientHeight`, чтобы он оказался центром под курсором. Конечно, нужно чтобы эта ширина и высота были известны, т.е. картинка либо уже была загружена, либо размеры мяча содержались в документе/CSS.
|
||||
|
||||
Код, который это делает и проверяет на размеры, вы найдете в полном решении:
|
||||
|
||||
[iframe border="1" src="solution" height="260" link edit]
|
|
@ -0,0 +1 @@
|
|||
{"name":"ball-move","plunk":"wgSOaNHgO69TbdmKGE9H"}
|
|
@ -0,0 +1 @@
|
|||
{"name":"ball-move-1","plunk":"PsBnyuCQRCYPm5wrrSzP"}
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
#field {
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
border: 10px groove black;
|
||||
background-color: #00FF00;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#ball {
|
||||
position: absolute;
|
||||
background: gray;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
Кликните на любое место поля, чтобы мяч перелетел туда.<br>
|
||||
|
||||
|
||||
<div id="field">
|
||||
<img src="http://js.cx/clipart/ball.gif" id="ball">
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var field = document.getElementById('field');
|
||||
var ball = document.getElementById('ball');
|
||||
|
||||
field.onclick = function(e) {
|
||||
|
||||
var fieldCoords = field.getBoundingClientRect();
|
||||
var fieldInnerCoords = {
|
||||
top: fieldCoords.top + field.clientTop,
|
||||
left: fieldCoords.left + field.clientLeft
|
||||
};
|
||||
|
||||
ball.style.left = e.clientX - fieldInnerCoords.left + 'px';
|
||||
ball.style.top = e.clientY - fieldInnerCoords.top + 'px';
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
{"name":"ball-move","plunk":"wgSOaNHgO69TbdmKGE9H"}
|
|
@ -0,0 +1,93 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
#field {
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
border: 10px groove black;
|
||||
background-color: #00FF00;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#ball {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
-webkit-transition: all 1s;
|
||||
-moz-transition: all 1s;
|
||||
-o-transition: all 1s;
|
||||
-ms-transition: all 1s;
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body style="height:2000px">
|
||||
|
||||
Кликните на любое место поля, чтобы мяч перелетел туда.<br>
|
||||
|
||||
|
||||
<div id="field">
|
||||
<img src="http://js.cx/clipart/ball.gif" id="ball">
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var field = document.getElementById('field');
|
||||
var ball = document.getElementById('ball');
|
||||
|
||||
|
||||
field.onclick = function(event) {
|
||||
|
||||
// координаты поля относительно окна
|
||||
var fieldCoords = this.getBoundingClientRect();
|
||||
|
||||
// координаты левого-верхнего внутреннего угла поля
|
||||
var fieldInnerCoords = {
|
||||
top: fieldCoords.top + field.clientTop,
|
||||
left: fieldCoords.left + field.clientLeft
|
||||
};
|
||||
|
||||
// разместить по клику,
|
||||
// но сдвинув относительно поля (т.к. position:relative)
|
||||
// и сдвинув на половину ширины/высоты
|
||||
// (!) используются координаты относительно окна clientX/Y, как и в fieldCoords
|
||||
var ballCoords = {
|
||||
top: event.clientY - fieldInnerCoords.top - ball.clientHeight / 2,
|
||||
left: event.clientX - fieldInnerCoords.left - ball.clientWidth / 2
|
||||
};
|
||||
|
||||
// вылезает за верхнюю границу - разместить по ней
|
||||
if(ballCoords.top < 0) ballCoords.top = 0;
|
||||
|
||||
// вылезает за левую границу - разместить по ней
|
||||
if(ballCoords.left < 0) ballCoords.left = 0;
|
||||
|
||||
|
||||
// вылезает за правую границу - разместить по ней
|
||||
if(ballCoords.left + ball.clientWidth > field.clientWidth) {
|
||||
ballCoords.left = field.clientWidth - ball.clientWidth;
|
||||
}
|
||||
|
||||
// вылезает за нижнюю границу - разместить по ней
|
||||
if(ballCoords.top + ball.clientHeight > field.clientHeight) {
|
||||
ballCoords.top = field.clientHeight - ball.clientHeight;
|
||||
}
|
||||
|
||||
ball.style.left = ballCoords.left + 'px';
|
||||
ball.style.top = ballCoords.top + 'px';
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,93 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
#field {
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
border: 10px groove black;
|
||||
background-color: #00FF00;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#ball {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
-webkit-transition: all 1s;
|
||||
-moz-transition: all 1s;
|
||||
-o-transition: all 1s;
|
||||
-ms-transition: all 1s;
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body style="height:2000px">
|
||||
|
||||
Кликните на любое место поля, чтобы мяч перелетел туда.<br>
|
||||
|
||||
|
||||
<div id="field">
|
||||
<img src="http://js.cx/clipart/ball.gif" id="ball">
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var field = document.getElementById('field');
|
||||
var ball = document.getElementById('ball');
|
||||
|
||||
|
||||
field.onclick = function(event) {
|
||||
|
||||
// координаты поля относительно окна
|
||||
var fieldCoords = this.getBoundingClientRect();
|
||||
|
||||
// координаты левого-верхнего внутреннего угла поля
|
||||
var fieldInnerCoords = {
|
||||
top: fieldCoords.top + field.clientTop,
|
||||
left: fieldCoords.left + field.clientLeft
|
||||
};
|
||||
|
||||
// разместить по клику,
|
||||
// но сдвинув относительно поля (т.к. position:relative)
|
||||
// и сдвинув на половину ширины/высоты
|
||||
// (!) используются координаты относительно окна clientX/Y, как и в fieldCoords
|
||||
var ballCoords = {
|
||||
top: event.clientY - fieldInnerCoords.top - ball.clientHeight / 2,
|
||||
left: event.clientX - fieldInnerCoords.left - ball.clientWidth / 2
|
||||
};
|
||||
|
||||
// вылезает за верхнюю границу - разместить по ней
|
||||
if(ballCoords.top < 0) ballCoords.top = 0;
|
||||
|
||||
// вылезает за левую границу - разместить по ней
|
||||
if(ballCoords.left < 0) ballCoords.left = 0;
|
||||
|
||||
|
||||
// вылезает за правую границу - разместить по ней
|
||||
if(ballCoords.left + ball.clientWidth > field.clientWidth) {
|
||||
ballCoords.left = field.clientWidth - ball.clientWidth;
|
||||
}
|
||||
|
||||
// вылезает за нижнюю границу - разместить по ней
|
||||
if(ballCoords.top + ball.clientHeight > field.clientHeight) {
|
||||
ballCoords.top = field.clientHeight - ball.clientHeight;
|
||||
}
|
||||
|
||||
ball.style.left = ballCoords.left + 'px';
|
||||
ball.style.top = ballCoords.top + 'px';
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,30 @@
|
|||
# Передвигать мяч по полю
|
||||
|
||||
[importance 5]
|
||||
|
||||
Сделайте так, что при клике по полю мяч перемещался на место клика.
|
||||
|
||||
[iframe src="solution" height="260" link]
|
||||
|
||||
Требования:
|
||||
<ul>
|
||||
<li>Мяч после перелёта должен становиться центром ровно под курсор мыши, если это возможно без вылета за край поля.</li>
|
||||
<li>CSS-анимацияне обязательна, но желательна.</li>
|
||||
<li>Мяч должен останавливаться у границ поля, ни в коем случае не вылетать за них.</li>
|
||||
<li>При прокрутке страницы ничего не должно ломаться.</li>
|
||||
</ul>
|
||||
|
||||
Решение лучше делать в два этапа.
|
||||
<ol>
|
||||
<li>Первый этап -- мяч сдвигается левым-верхним углом под курсор мыши.</li>
|
||||
<li>Второй этап -- мяч сдвигается центром и добавляется проверка на край поля.</li>
|
||||
</ol>
|
||||
|
||||
Замечания:
|
||||
<ul>
|
||||
<li>Код не должен зависеть от конкретных размеров мяча и поля.</li>
|
||||
<li>Текущий HTML/CSS нельзя менять, можно лишь "украшать" (анимация).</li>
|
||||
<li>Вам пригодятся свойства `event.clientX/event.clientY`</li>
|
||||
</ul>
|
||||
|
||||
[edit src="task" task/]
|
|
@ -0,0 +1 @@
|
|||
{"name":"ball-move-src","plunk":"jhWqs0d3JMN7SiiHJOpv"}
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
#field {
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
border: 10px groove black;
|
||||
background-color: #00FF00;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#ball {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -20px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="height:2000px">
|
||||
|
||||
Кликните на любое место поля, чтобы мяч перелетел туда.<br>
|
||||
Мяч никогда не вылетит за границы поля.
|
||||
|
||||
|
||||
<div id="field">
|
||||
<img src="http://js.cx/clipart/ball.gif" id="ball">
|
||||
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,109 @@
|
|||
# Объект события
|
||||
|
||||
Чтобы хорошо обработать событие, недостаточно знать о том, что это -- "клик" или "нажатие клавиши". Могут понадобиться детали: координаты курсора, введённый символ и другие, в зависимости от события.
|
||||
|
||||
**Детали произошедшего браузер записывает в "объект события", который передаётся первым аргументом в обработчик.**
|
||||
[cut]
|
||||
|
||||
## Получение объекта события
|
||||
|
||||
Пример ниже демонстрирует использования объекта события:
|
||||
|
||||
```html
|
||||
<!--+ run -->
|
||||
<input type="button" value="Нажми меня" id="elem">
|
||||
|
||||
<script>
|
||||
elem.onclick = function(*!*event*/!*) {
|
||||
alert(event.type + " на " + event.currentTarget);
|
||||
alert(event.clientX + ":" + event.clientY);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
Свойства объекта `event`:
|
||||
<dl>
|
||||
<dt>`event.type`</dt>
|
||||
<dd>Тип события, в данном случае `click`</dd>
|
||||
<dt>`event.currentTarget`</dt>
|
||||
<dd>Элемент, на котором сработал обработчик -- то же, что и `this`, но бывают ситуации, когда обработчик является методом объекта и его `this` при помощи `bind` привязан к объекту, тогда `event.currentTarget` полезен.</dd>
|
||||
<dt>`event.clientX / event.clientY`</dt>
|
||||
<dd>Координаты курсора в момент клика (относительно окна)</dd>
|
||||
</dl>
|
||||
|
||||
Есть также и ряд других свойств, в зависимости от событий, которые мы разберём в дальнейших главах, когда будем подробно знакомиться с событиями мыши, клавиатуры и так далее.
|
||||
|
||||
[smart header="Объект события доступен и в HTML"]
|
||||
При назначении обработчика в HTML, тоже можно использовать переменную `event`, это будет работать кросс-браузерно:
|
||||
|
||||
```html
|
||||
<!--+ autorun height=auto -->
|
||||
<input type="button" onclick="*!*alert(event.type)*/!*" value="Тип события">
|
||||
```
|
||||
|
||||
Это возможно потому, что когда браузер из атрибута создаёт функцию-обработчик, то она выглядит так: `function(event) { alert(event.type) }`. То есть, её первый аргумент называется `"event"`.
|
||||
[/smart]
|
||||
|
||||
## Особенности IE8-
|
||||
|
||||
IE8- вместо передачи параметра обработчику создаёт глобальный объект `window.event`. Обработчик может обратиться к нему.
|
||||
|
||||
Работает это так:
|
||||
|
||||
```js
|
||||
elem.onclick = function() {
|
||||
// window.event - объект события
|
||||
alert( window.event.clientX );
|
||||
};
|
||||
```
|
||||
|
||||
### Кроссбраузерное решение
|
||||
|
||||
Универсальное решение для получения объекта события:
|
||||
|
||||
```js
|
||||
element.onclick = function(event) {
|
||||
event = event || window.event; // (*)
|
||||
|
||||
// Теперь event - объект события во всех браузерах.
|
||||
};
|
||||
```
|
||||
|
||||
Строка `(*)`, в случае, если функция не получила `event` (IE8-), использует `window.event`.-событие `event`.
|
||||
|
||||
Можно написать и иначе, если мы сами не используем переменную `event` в замыкании:
|
||||
|
||||
```js
|
||||
element.onclick = function(e) {
|
||||
e = e || event;
|
||||
|
||||
// Теперь e - объект события во всех браузерах.
|
||||
};
|
||||
```
|
||||
|
||||
## Итого
|
||||
|
||||
<ul>
|
||||
<li>Объект события содержит ценную информацию о деталях события.</li>
|
||||
<li>Он передается первым аргументом `event` в обработчик для всех браузеров, кроме IE8-, в которых используется глобальная переменная `window.event`.</li>
|
||||
</ul>
|
||||
|
||||
Кросс-браузерно для JavaScript-обработчика получаем объект события так:
|
||||
|
||||
```js
|
||||
element.onclick = function(event) {
|
||||
event = event || window.event;
|
||||
|
||||
// Теперь event - объект события во всех браузерах.
|
||||
};
|
||||
```
|
||||
|
||||
Еще вариант:
|
||||
|
||||
```js
|
||||
element.onclick = function(e) {
|
||||
e = e || event; // если нет другой внешней переменной event
|
||||
...
|
||||
};
|
||||
```
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue