diff --git a/2-ui/3-event-details/1-mouse-events-basics/article.md b/2-ui/3-event-details/1-mouse-events-basics/article.md index 2ec6799b3a..fe88929d1a 100644 --- a/2-ui/3-event-details/1-mouse-events-basics/article.md +++ b/2-ui/3-event-details/1-mouse-events-basics/article.md @@ -1,9 +1,4 @@ -<<<<<<< HEAD # 마우스 이벤트 -======= - -# Mouse events ->>>>>>> upstream/master 이번 챕터에선 마우스 이벤트와 마우스 이벤트 객체의 프로퍼티에 대해 자세히 다루겠습니다. @@ -44,15 +39,9 @@ ```online 아래 버튼을 클릭 또는 더블클릭해 실제 마우스 버튼을 클릭했을 때 어떤 일이 발생하는지 알아봅시다. -<<<<<<< HEAD 모든 마우스 이벤트가 버튼 아래 창에 기록되는데, 이벤트 발생 간격이 1초 이상일 때는 이벤트 사이에 가로 선이 추가되도록 해놓았습니다. 이벤트 이름 옆엔 어떤 마우스 버튼이 이벤트를 발생시켰는지를 알려주는 `button` 프로퍼티도 보이는데, `button` 프로퍼티에 대한 내용은 바로 아래에서 설명하도록 하겠습니다. -======= -On the teststand below, all mouse events are logged, and if there is more than a 1 second delay between them, they are separated by a horizontal rule. - -Also, we can see the `button` property that allows us to detect the mouse button; it's explained below. ->>>>>>> upstream/master
``` @@ -63,37 +52,21 @@ Also, we can see the `button` property that allows us to detect the mouse button `click` 이벤트는 마우스 왼쪽 버튼을, `contextmenu` 이벤트는 마우스 오른쪽 버튼을 눌렀을 때 발생하기 때문에 `click`과 `contextmenu` 이벤트를 다룰 땐 보통 `button` 프로퍼티를 사용하지 않습니다. -<<<<<<< HEAD 반면 `mousedown`이벤트나 `mouseup` 이벤트를 다룰 땐 해당 이벤트의 핸들러에 `event.button`을 명시해 줘야 할 수 있습니다. 이 이벤트들은 마우스 버튼 어디에서나 발생할 수 있는데 `button` 프로퍼티를 사용해야 정확히 어떤 버튼에서 이벤트가 발생했는지 알 수 있기 때문입니다. -======= -On the other hand, `mousedown` and `mouseup` handlers may need `event.button`, because these events trigger on any button, so `button` allows to distinguish between "right-mousedown" and "left-mousedown". ->>>>>>> upstream/master 주요 `event.button` 프로퍼티 값을 정리하면 다음과 같습니다. | 버튼 | `event.button` | |--------------|----------------| -<<<<<<< HEAD | 왼쪽(주요 버튼) | 0 | | 가운데(보조 버튼) | 1 | | 오른쪽 (두 번째 버튼) | 2 | | X1(뒤로 가기 버튼) | 3 | | X2(앞으로 가기 버튼) | 4 | -======= -| Left button (primary) | 0 | -| Middle button (auxiliary) | 1 | -| Right button (secondary) | 2 | -| X1 button (back) | 3 | -| X2 button (forward) | 4 | ->>>>>>> upstream/master 상당수의 마우스는 왼쪽, 오른쪽 버튼만 가지고 있기 때문에 이 마우스들이 만들어내는 `event.button` 값은 `0`이나 `2`가 됩니다. 터치를 지원하는 기기들도 사람이 해당 기기를 터치했을 때 유사한 이벤트를 만듭니다. -<<<<<<< HEAD 참고로 `buttons`라는 프로퍼티도 있는데, 이 프로퍼티는 여러 개의 버튼을 한꺼번에 눌렀을 때 해당 버튼들에 대한 정보를 정수 형태로 저장해 줍니다. 실무에서 `buttons` 프로퍼티를 만날 일은 극히 드물긴 하지만 혹시라도 필요하다면[MDN](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons)에서 확인해보시길 바랍니다. -======= -Also there's `event.buttons` property that has all currently pressed buttons as an integer, one bit per button. In practice this property is very rarely used, you can find details at [MDN](mdn:/api/MouseEvent/buttons) if you ever need it. ->>>>>>> upstream/master ```warn header="역사의 뒤안길로 사라진 `event.which`" 오래된 코드를 보다 보면 `event.which`라는 프로퍼티를 발견할 수 있습니다. `event.which` 프로퍼티는 어떤 버튼을 클릭했는지 알려주는 비표준 프로퍼티로 다음과 같은 값을 가집니다. @@ -181,15 +154,9 @@ Windows와 Linux는 `key:Alt`, `key:Shift`, `key:Ctrl` 키를 지원합니다. ## mousedown 이벤트와 선택 막기 -<<<<<<< HEAD 글자 위에서 마우스를 더블클릭하면 글자가 선택되는데, 이런 기본 동작이 사용자 경험을 해칠 때가 있습니다. `dblclick` 이벤트가 발생하면 얼럿 창을 띄우고 싶다고 가정해 봅시다. 제대로 코드를 작성했음에도 불구하고 핸들러가 실행되는 동시에 글자가 선택되는 불필요한 부수효과가 발생하였습니다. -======= -Double mouse click has a side effect that may be disturbing in some interfaces: it selects text. - -For instance, double-clicking on the text below selects it in addition to our handler: ->>>>>>> upstream/master ```html autorun height=50 이곳을 더블클릭해주세요. diff --git a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/article.md b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/article.md index d409c3f127..580067c10c 100644 --- a/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/article.md +++ b/2-ui/3-event-details/3-mousemove-mouseover-mouseout-mouseenter-mouseleave/article.md @@ -218,4 +218,4 @@ These things are good to note: Events `mouseover/out` trigger even when we go from the parent element to a child element. The browser assumes that the mouse can be only over one element at one time -- the deepest one. -Events `mouseenter/leave` are different in that aspect: they only trigger when the mouse comes in and out the element as a whole. Also they do not bubble. +Events `mouseenter/leave` are different in that aspect: they only trigger when the mouse comes in and out the element as a whole. Also they do not bubble. \ No newline at end of file diff --git a/2-ui/3-event-details/4-mouse-drag-and-drop/article.md b/2-ui/3-event-details/4-mouse-drag-and-drop/article.md index e20f93bd34..664069e943 100644 --- a/2-ui/3-event-details/4-mouse-drag-and-drop/article.md +++ b/2-ui/3-event-details/4-mouse-drag-and-drop/article.md @@ -18,16 +18,11 @@ 2. 이후 `mousemove`에서 `position:absolute`의 `left∙top`을 변경합니다. 3. `mouseup`에서는 드래그 앤 드롭 완료와 관련된 모든 작업을 수행합니다. -<<<<<<< HEAD 여기까지가 기본 알고리즘입니다. 이후에는 이동 중인 요소 아래에 있는 다른 요소를 강조하는 기능을 알아보겠습니다. -======= -These are the basics. Later we'll see how to add other features, such as highlighting current underlying elements while we drag over them. ->>>>>>> upstream/master 공을 드래그하는 구현 방법은 다음과 같습니다. ```js -<<<<<<< HEAD ball.onmousedown = function(event) { // (1) absolute 속성과 zIndex 프로퍼티를 수정해 공이 제일 위에서 움직이기 위한 준비를 합니다. ball.style.position = 'absolute'; @@ -36,16 +31,6 @@ ball.onmousedown = function(event) { // 현재 위치한 부모에서 body로 직접 이동하여 // body를 기준으로 위치를 지정합니다. document.body.append(ball); -======= -ball.onmousedown = function(event) { - // (1) prepare to moving: make absolute and on top by z-index - ball.style.position = 'absolute'; - ball.style.zIndex = 1000; - - // move it out of any current parents directly into body - // to make it positioned relative to the body - document.body.append(ball); ->>>>>>> upstream/master // 공을 pageX, pageY 좌표 중앙에 위치하게 합니다. function moveAt(pageX, pageY) { @@ -108,22 +93,14 @@ document의 중간이나 윈도우 어딘가로 점프 되는 현상을 잡기 ## 올바른 위치 지정 -<<<<<<< HEAD 위 예제 코드에서 공은 항상 포인터 아래로 이동합니다. -======= -In the examples above the ball is always moved so that its center is under the pointer: ->>>>>>> upstream/master ```js ball.style.left = pageX - ball.offsetWidth / 2 + 'px'; ball.style.top = pageY - ball.offsetHeight / 2 + 'px'; ``` -<<<<<<< HEAD 나쁘진 않습니다. 다만, 몇 가지 부작용이 있습니다. 드래그 앤 드롭을 시작하기 위해 공 위 어디에서든 `mousedown`을 할 수 있습니다. 공의 가장자리에서 `mousedown`을 하게 되면, 마우스 포인터 아래로 공이 갑자기 점프 되는 부작용이 발생합니다. -======= -Not bad, but there's a side effect. To initiate the drag'n'drop, we can `mousedown` anywhere on the ball. But if "take" it from its edge, then the ball suddenly "jumps" to become centered under the mouse pointer. ->>>>>>> upstream/master 포인터를 기준으로 요소의 초기 이동을 유지하는 방법이 포인터 중앙으로 요소를 이동시키는 방법보다 더 좋습니다. @@ -147,11 +124,7 @@ Not bad, but there's a side effect. To initiate the drag'n'drop, we can `mousedo ```js // onmousemove -<<<<<<< HEAD // 공은 고정된 포지션을 갖습니다. -======= - // ball has position:absolute ->>>>>>> upstream/master ball.style.left = event.pageX - *!*shiftX*/!* + 'px'; ball.style.top = event.pageY - *!*shiftY*/!* + 'px'; ``` @@ -246,11 +219,7 @@ ball.ondragstart = function() { 그러면 무엇을 해야 할까요? -<<<<<<< HEAD `document.elementFromPoint(clientX, clientY)`라는 메서드가 있습니다. 주어진 윈도우 기준 좌표에서 가장 많이 중첩된 요소를 반환합니다. (윈도우 밖의 좌표는 null) -======= -There's a method called `document.elementFromPoint(clientX, clientY)`. It returns the most nested element on given window-relative coordinates (or `null` if given coordinates are out of the window). If there are multiple overlapping elements on the same coordinates, then the topmost one is returned. ->>>>>>> upstream/master 다음과 같이 마우스 이벤트 핸들러에서 포인터 아래에 드롭 가능성을 감지할 수 있습니다. @@ -307,11 +276,7 @@ function onMouseMove(event) { } ``` -<<<<<<< HEAD 아래 예시에서 공을 축구 골대 위로 드래그하면 골대가 강조 표시됩니다. -======= -In the example below when the ball is dragged over the soccer goal, the goal is highlighted. ->>>>>>> upstream/master [codetabs height=250 src="ball4"] @@ -335,8 +300,4 @@ In the example below when the ball is dragged over the soccer goal, the goal is - `mousedown/up`에 이벤트 위임을 사용할 수 있습니다. `event.target`을 확인하는 넓은 영역의 이벤트 핸들러는 수백 개의 요소에 대한 드래그 앤 드롭을 관리할 수 있습니다. - 등등 -<<<<<<< HEAD `DragZone`, `Droppable`, `Draggable` 및 기타 클래스 등 아키텍처를 구축하는 프레임워크가 있습니다. 대부분은 앞서 드래그와 드롭에 대한 설명과 유사한 작업을 하므로 이해하기 쉽습니다. 때로는 제3의 솔루션 적용보다 쉽게 수행할 수 있습니다. -======= -There are frameworks that build architecture over it: `DragZone`, `Droppable`, `Draggable` and other classes. Most of them do the similar stuff to what's described above, so it should be easy to understand them now. Or roll your own, as you can see that that's easy enough to do, sometimes easier than adapting a third-party solution. ->>>>>>> upstream/master diff --git a/2-ui/3-event-details/6-pointer-events/article.md b/2-ui/3-event-details/6-pointer-events/article.md index 557f7b31a5..174e0fe095 100644 --- a/2-ui/3-event-details/6-pointer-events/article.md +++ b/2-ui/3-event-details/6-pointer-events/article.md @@ -1,44 +1,36 @@ -# Pointer events +# 포인터 이벤트 -Pointer events are a modern way to handle input from a variety of pointing devices, such as a mouse, a pen/stylus, a touchscreen, and so on. +포인터 이벤트(Pointer events)는 마우스, 펜·스타일러스, 터치스크린 같은 다양한 포인팅 기기의 입력을 처리하는 현대적인 방법입니다. -## The brief history +## 간략한 역사 -Let's make a small overview, so that you understand the general picture and the place of Pointer Events among other event types. +포인터 이벤트가 다른 이벤트 유형 사이에서 어떤 위치에 있는지 전체 그림을 이해할 수 있도록 간략히 살펴보겠습니다. -- Long ago, in the past, there were only mouse events. +- 오래전에는 마우스 이벤트만 있었습니다. - Then touch devices became widespread, phones and tablets in particular. For the existing scripts to work, they generated (and still generate) mouse events. For instance, tapping a touchscreen generates `mousedown`. So touch devices worked well with web pages. -<<<<<<< HEAD - -======= + 그러다 터치 기기, 특히 휴대 전화와 태블릿이 널리 보급되었습니다. 기존 스크립트가 동작하도록 터치 기기는 마우스 이벤트를 생성했고 지금도 생성합니다. 예를 들어 터치스크린을 탭 하면 `mousedown`이 발생합니다. 덕분에 터치 기기는 웹 페이지와 잘 동작했습니다. ->>>>>>> upstream/master - But touch devices have more capabilities than a mouse. For example, it's possible to touch multiple points at once ("multi-touch"). Although, mouse events don't have necessary properties to handle such multi-touches. + 하지만 터치 기기는 마우스보다 더 많은 기능을 제공합니다. 예를 들어 여러 지점을 동시에 터치하는 '멀티 터치'가 가능합니다. 하지만 마우스 이벤트에는 이런 멀티 터치를 처리하는 데 필요한 프로퍼티가 없습니다. -- So touch events were introduced, such as `touchstart`, `touchend`, `touchmove`, that have touch-specific properties (we don't cover them in detail here, because pointer events are even better). +- 그래서 `touchstart`, `touchend`, `touchmove`처럼 터치에 특화된 프로퍼티를 가진 터치 이벤트가 도입되었습니다. 포인터 이벤트가 더 나은 방식이므로 여기서는 자세히 다루지 않겠습니다. - Still, it wasn't enough, as there are many other devices, such as pens, that have their own features. Also, writing code that listens for both touch and mouse events was cumbersome. + 하지만 그것만으로는 부족했습니다. 펜처럼 저마다 고유 기능을 가진 다른 기기도 많았기 때문입니다. 터치 이벤트와 마우스 이벤트를 모두 수신하는 코드를 작성하는 일도 번거로웠습니다. -- To solve these issues, the new standard Pointer Events was introduced. It provides a single set of events for all kinds of pointing devices. +- 이런 문제를 해결하기 위해 새로운 표준인 포인터 이벤트가 도입되었습니다. 포인터 이벤트는 모든 종류의 포인팅 기기에 대해 하나의 이벤트 집합을 제공합니다. -<<<<<<< HEAD -As of now, [Pointer Events Level 2](https://www.w3.org/TR/pointerevents2/) specification is supported in all major browsers, while the newer [Pointer Events Level 3](https://w3c.github.io/pointerevents/) is in the works and is mostly compartible with Pointer Events level 2. -======= -As of now, [Pointer Events Level 2](https://www.w3.org/TR/pointerevents2/) specification is supported in all major browsers, while the newer [Pointer Events Level 3](https://w3c.github.io/pointerevents/) is in the works and is mostly compatible with Pointer Events level 2. ->>>>>>> upstream/master +현재 [Pointer Events Level 2](https://www.w3.org/TR/pointerevents2/) 명세는 모든 주요 브라우저에서 지원됩니다. 더 최신 버전인 [Pointer Events Level 3](https://w3c.github.io/pointerevents/)는 작업 중이며 Pointer Events Level 2와 대부분 호환됩니다. -Unless you develop for old browsers, such as Internet Explorer 10, or for Safari 12 or below, there's no point in using mouse or touch events any more -- we can switch to pointer events. +Internet Explorer 10이나 Safari 12 이하 같은 구형 브라우저를 지원해야 하는 경우가 아니라면, 이제 마우스 이벤트나 터치 이벤트를 사용할 이유가 없습니다. 포인터 이벤트로 전환하면 됩니다. -Then your code will work well with both touch and mouse devices. +그러면 터치 기기와 마우스 기기 모두에서 코드가 잘 동작합니다. -That said, there are some important peculiarities that one should know in order to use Pointer Events correctly and avoid surprises. We'll make note of them in this article. +다만 포인터 이벤트를 올바르게 사용하고 예상치 못한 동작을 피하려면 알아두어야 할 중요한 특징이 몇 가지 있습니다. 이 챕터에서 그 특징을 짚어보겠습니다. -## Pointer event types +## 포인터 이벤트 종류 -Pointer events are named similarly to mouse events: +포인터 이벤트의 이름은 마우스 이벤트와 유사하게 지어졌습니다. -| Pointer event | Similar mouse event | +| 포인터 이벤트 | 유사한 마우스 이벤트 | |---------------|-------------| | `pointerdown` | `mousedown` | | `pointerup` | `mouseup` | @@ -51,201 +43,142 @@ Pointer events are named similarly to mouse events: | `gotpointercapture` | - | | `lostpointercapture` | - | -As we can see, for every `mouse`, there's a `pointer` that plays a similar role. Also there are 3 additional pointer events that don't have a corresponding `mouse...` counterpart, we'll explain them soon. +표에서 볼 수 있듯이 모든 `mouse`에는 비슷한 역할을 하는 `pointer`가 대응됩니다. 여기에 대응하는 `mouse...` 이벤트가 없는 포인터 이벤트도 세 가지 있는데, 곧 설명하겠습니다. -```smart header="Replacing `mouse` with `pointer` in our code" -We can replace `mouse` events with `pointer` in our code and expect things to continue working fine with mouse. +```smart header="코드에서 `mouse`를 `pointer`로 바꾸기" +코드에서 `mouse` 이벤트를 `pointer`로 바꿔도 마우스에서 계속 잘 동작합니다. -<<<<<<< HEAD -The support for touch devices will also "magically" improve. Although, we may need to add `touch-action: none` in some places in CSS. We'll cover it below in the section about `pointercancel`. -======= -The support for touch devices will also "magically" improve. Although, we may need to add `touch-action: none` in some places in CSS. We'll cover it below in the section about `pointercancel`. ->>>>>>> upstream/master +터치 기기 지원도 '마법처럼' 좋아집니다. 다만 CSS에서 몇 군데에 `touch-action: none`을 추가해야 할 수도 있습니다. 아래 `pointercancel`에서 다루겠습니다. ``` -## Pointer event properties +## 포인터 이벤트 프로퍼티 -Pointer events have the same properties as mouse events, such as `clientX/Y`, `target`, etc., plus some others: +포인터 이벤트는 `clientX·clientY`, `target` 등 마우스 이벤트와 동일한 프로퍼티를 가지며, 여기에 몇 가지 프로퍼티가 더 있습니다. -- `pointerId` - the unique identifier of the pointer causing the event. -<<<<<<< HEAD - - Browser-generated. Allows us to handle multiple pointers, such as a touchscreen with stylus and multi-touch (examples will follow). -- `pointerType` - the pointing device type. Must be a string, one of: "mouse", "pen" or "touch". -======= +- `pointerId` - 이벤트를 일으킨 포인터의 고유 식별자입니다. - Browser-generated. Allows us to handle multiple pointers, such as a touchscreen with stylus and multi-touch (examples will follow). -- `pointerType` - the pointing device type. Must be a string, one of: "mouse", "pen" or "touch". ->>>>>>> upstream/master + 브라우저가 생성합니다. 스타일러스와 멀티 터치를 지원하는 터치스크린처럼 여러 포인터를 처리할 수 있게 해줍니다. 예시는 뒤에서 살펴보겠습니다. +- `pointerType` - 포인팅 기기의 유형입니다. "mouse", "pen", "touch" 중 하나인 문자열이어야 합니다. - We can use this property to react differently on various pointer types. -- `isPrimary` - is `true` for the primary pointer (the first finger in multi-touch). + 이 프로퍼티를 사용하면 포인터 유형에 따라 다르게 반응할 수 있습니다. +- `isPrimary` - 주 포인터, 즉 멀티 터치에서 첫 번째 손가락이면 `true`입니다. -Some pointer devices measure contact area and pressure, e.g. for a finger on the touchscreen, there are additional properties for that: +일부 포인터 기기는 접촉 면적과 압력을 측정합니다. 예를 들어 터치스크린에 닿은 손가락에 대해 다음과 같은 추가 프로퍼티가 있습니다. -<<<<<<< HEAD -- `width` - the width of the area where the pointer (e.g. a finger) touches the device. Where unsupported, e.g. for a mouse, it's always `1`. -======= -- `width` - the width of the area where the pointer (e.g. a finger) touches the device. Where unsupported, e.g. for a mouse, it's always `1`. ->>>>>>> upstream/master -- `height` - the height of the area where the pointer touches the device. Where unsupported, it's always `1`. -- `pressure` - the pressure of the pointer tip, in range from 0 to 1. For devices that don't support pressure must be either `0.5` (pressed) or `0`. -- `tangentialPressure` - the normalized tangential pressure. -- `tiltX`, `tiltY`, `twist` - pen-specific properties that describe how the pen is positioned relative to the surface. +- `width` - 포인터, 예를 들어 손가락이 기기에 닿은 영역의 너비입니다. 마우스처럼 지원되지 않을 때는 항상 `1`입니다. +- `height` - 포인터가 기기에 닿은 영역의 높이입니다. 지원되지 않을 때는 항상 `1`입니다. +- `pressure` - 포인터 끝의 압력으로, 범위는 0부터 1까지입니다. 압력을 지원하지 않는 기기에서는 `0.5`(눌림) 또는 `0`이어야 합니다. +- `tangentialPressure` - 정규화된 접선 방향 압력입니다. +- `tiltX`, `tiltY`, `twist` - 펜이 표면을 기준으로 어떻게 놓였는지 설명하는 펜 전용 프로퍼티입니다. -These properties aren't supported by most devices, so they are rarely used. You can find the details about them in the [specification](https://w3c.github.io/pointerevents/#pointerevent-interface) if needed. +이 프로퍼티들은 대부분의 기기에서 지원되지 않아 잘 사용되지 않습니다. 필요하다면 [명세](https://w3c.github.io/pointerevents/#pointerevent-interface)에서 자세한 내용을 확인할 수 있습니다. -## Multi-touch +## 멀티 터치 -One of the things that mouse events totally don't support is multi-touch: a user can touch in several places at once on their phone or tablet, or perform special gestures. +마우스 이벤트가 전혀 지원하지 않는 기능 중 하나가 멀티 터치입니다. 사용자는 휴대 전화나 태블릿에서 여러 곳을 동시에 터치하거나 특수 제스처를 수행할 수 있습니다. -Pointer Events allow handling multi-touch with the help of the `pointerId` and `isPrimary` properties. +포인터 이벤트는 `pointerId`와 `isPrimary` 프로퍼티를 활용해 멀티 터치를 처리할 수 있습니다. -Here's what happens when a user touches a touchscreen in one place, then puts another finger somewhere else on it: +사용자가 터치스크린의 한 곳을 터치한 다음 다른 손가락을 다른 곳에 올리면 다음과 같은 일이 발생합니다. -1. At the first finger touch: - - `pointerdown` with `isPrimary=true` and some `pointerId`. -2. For the second finger and more fingers (assuming the first one is still touching): - - `pointerdown` with `isPrimary=false` and a different `pointerId` for every finger. +1. 첫 번째 손가락이 터치될 때 + - `isPrimary=true`와 어떤 `pointerId`를 가진 `pointerdown`이 발생합니다. +2. 첫 번째 손가락이 아직 닿아 있다고 가정하고 두 번째 손가락과 그 이후의 손가락이 터치된 경우 + - 손가락마다 `isPrimary=false`와 서로 다른 `pointerId`를 가진 `pointerdown`이 발생합니다. -Please note: the `pointerId` is assigned not to the whole device, but for each touching finger. If we use 5 fingers to simultaneously touch the screen, we have 5 `pointerdown` events, each with their respective coordinates and a different `pointerId`. +주의할 점은 `pointerId`가 기기 전체가 아니라 터치 중인 각 손가락에 할당된다는 것입니다. 손가락 5개로 화면을 동시에 터치하면 `pointerdown` 이벤트가 5개 발생하고, 각 이벤트는 저마다의 좌표와 서로 다른 `pointerId`를 가집니다. -The events associated with the first finger always have `isPrimary=true`. +첫 번째 손가락과 관련된 이벤트는 항상 `isPrimary=true`를 가집니다. -We can track multiple touching fingers using their `pointerId`. When the user moves and then removes a finger, we get `pointermove` and `pointerup` events with the same `pointerId` as we had in `pointerdown`. +`pointerId`를 사용하면 여러 손가락의 터치를 추적할 수 있습니다. 사용자가 손가락을 움직인 다음 떼면, `pointerdown`에서 받았던 것과 같은 `pointerId`를 가진 `pointermove`와 `pointerup` 이벤트가 발생합니다. ```online -Here's the demo that logs `pointerdown` and `pointerup` events: +`pointerdown`과 `pointerup` 이벤트를 기록하는 데모입니다. [iframe src="multitouch" edit height=200] -Please note: you must be using a touchscreen device, such as a phone or a tablet, to actually see the difference in `pointerId/isPrimary`. For single-touch devices, such as a mouse, there'll be always same `pointerId` with `isPrimary=true`, for all pointer events. +참고로 `pointerId·isPrimary`의 차이를 실제로 확인하려면 휴대 전화나 태블릿 같은 터치스크린 기기를 사용해야 합니다. 마우스 같은 단일 터치 기기에서는 모든 포인터 이벤트에서 항상 같은 `pointerId`와 `isPrimary=true`가 사용됩니다. ``` -## Event: pointercancel +## pointercancel 이벤트 -<<<<<<< HEAD -The `pointercancel` event fires when there's an ongoing pointer interaction, and then something happens that causes it to be aborted, so that no more pointer events are generated. +`pointercancel` 이벤트는 포인터 상호작용이 진행 중일 때, 그 상호작용을 중단시키는 일이 발생해 더 이상 포인터 이벤트가 생성되지 않을 때 발생합니다. -Such causes are: -- The pointer device hardware was physically disabled. -- The device orientation changed (tablet rotated). -======= -The `pointercancel` event fires when there's an ongoing pointer interaction, and then something happens that causes it to be aborted, so that no more pointer events are generated. +원인은 다음과 같습니다. +- 포인터 기기 하드웨어가 물리적으로 비활성화된 경우 +- 기기 방향이 바뀐 경우(태블릿 회전) +- 브라우저가 상호작용을 마우스 제스처나 확대·이동 동작 등으로 보고 직접 처리하기로 한 경우 -Such causes are: -- The pointer device hardware was physically disabled. -- The device orientation changed (tablet rotated). ->>>>>>> upstream/master -- The browser decided to handle the interaction on its own, considering it a mouse gesture or zoom-and-pan action or something else. +`pointercancel`이 어떤 영향을 주는지 실제 예시로 확인해 보겠습니다. -We'll demonstrate `pointercancel` on a practical example to see how it affects us. + 글의 초반부처럼 공을 드래그 앤 드롭하는 기능을 구현한다고 가정해 봅시다. -Let's say we're implementing drag'n'drop for a ball, just as in the beginning of the article . +사용자 동작의 흐름과 그에 대응하는 이벤트는 다음과 같습니다. -Here is the flow of user actions and the corresponding events: +1) 사용자가 이미지를 눌러 드래그를 시작합니다. + - `pointerdown` 이벤트가 발생합니다. +2) 그런 다음 포인터를 움직이기 시작합니다. 따라서 이미지가 드래그됩니다. + - `pointermove`가 발생합니다. 여러 번 발생할 수도 있습니다. +3) 그런데 여기서 예상치 못한 일이 벌어집니다! 브라우저에는 이미지를 위한 기본 드래그 앤 드롭 지원이 있는데, 이 기능이 드래그 앤 드롭 과정을 가로채면서 `pointercancel` 이벤트를 발생시킵니다. + - 이제 브라우저가 이미지의 드래그 앤 드롭을 직접 처리합니다. 사용자는 공 이미지를 브라우저 밖으로 끌어내 메일 프로그램이나 파일 관리자에 놓을 수도 있습니다. + - 더 이상 `pointermove` 이벤트는 발생하지 않습니다. -1) The user presses on an image, to start dragging - - `pointerdown` event fires -2) Then they start moving the pointer (thus dragging the image) - - `pointermove` fires, maybe several times -3) And then the surprise happens! The browser has native drag'n'drop support for images, that kicks in and takes over the drag'n'drop process, thus generating `pointercancel` event. - - The browser now handles drag'n'drop of the image on its own. The user may even drag the ball image out of the browser, into their Mail program or a File Manager. - - No more `pointermove` events for us. - -So the issue is that the browser "hijacks" the interaction: `pointercancel` fires in the beginning of the "drag-and-drop" process, and no more `pointermove` events are generated. +따라서 문제는 브라우저가 상호작용을 '가로챈다'라는 데 있습니다. '드래그 앤 드롭' 과정이 시작될 때 `pointercancel`이 발생하고, 이후에는 `pointermove` 이벤트가 더 이상 생성되지 않습니다. ```online -<<<<<<< HEAD -Here's the drag'n'drop demo with loggin of pointer events (only `up/down`, `move` and `cancel`) in the `textarea`: -======= -Here's the drag'n'drop demo with logging of pointer events (only `up/down`, `move` and `cancel`) in the `textarea`: ->>>>>>> upstream/master +`textarea`에 포인터 이벤트(`up·down`, `move`, `cancel`만)를 기록하는 드래그 앤 드롭 데모입니다. [iframe src="ball" height=240 edit] ``` -We'd like to implement the drag'n'drop on our own, so let's tell the browser not to take it over. +직접 드래그 앤 드롭을 구현하려면 브라우저가 이를 가로채지 않도록 해야 합니다. -**Prevent the default browser action to avoid `pointercancel`.** +**`pointercancel`을 방지하려면 브라우저 기본 동작을 막으세요.** -We need to do two things: +두 가지 작업이 필요합니다. -1. Prevent native drag'n'drop from happening: - - We can do this by setting `ball.ondragstart = () => false`, just as described in the article . - - That works well for mouse events. -2. For touch devices, there are other touch-related browser actions (besides drag'n'drop). To avoid problems with them too: -<<<<<<< HEAD - - Prevent them by setting `#ball { touch-action: none }` in CSS. -======= - - Prevent them by setting `#ball { touch-action: none }` in CSS. ->>>>>>> upstream/master - - Then our code will start working on touch devices. +1. 기본 드래그 앤 드롭이 발생하지 않도록 막습니다. + - 에서 설명한 것처럼 `ball.ondragstart = () => false`를 설정하면 됩니다. + - 마우스 이벤트에서는 이 방법이 잘 동작합니다. +2. 터치 기기에는 드래그 앤 드롭 외에도 터치와 관련된 다른 브라우저 동작이 있습니다. 이 동작 때문에 생기는 문제도 피하려면 다음과 같이 합니다. + - CSS에서 `#ball { touch-action: none }`을 설정해 막습니다. + - 그러면 코드가 터치 기기에서도 작동하기 시작합니다. -After we do that, the events will work as intended, the browser won't hijack the process and doesn't emit `pointercancel`. +이렇게 하면 이벤트가 의도대로 동작하고, 브라우저가 과정을 가로채거나 `pointercancel`을 발생시키지 않습니다. ```online -This demo adds these lines: +이 데모는 위 코드를 추가한 버전입니다. [iframe src="ball-2" height=240 edit] -As you can see, there's no `pointercancel` any more. +확인할 수 있듯이 더 이상 `pointercancel`은 발생하지 않습니다. ``` -Now we can add the code to actually move the ball, and our drag'n'drop will work for mouse devices and touch devices. - -## Pointer capturing - -Pointer capturing is a special feature of pointer events. - -The idea is very simple, but may seem quite odd at first, as nothing like that exists for any other event type. - -The main method is: -<<<<<<< HEAD -- `elem.setPointerCapture(pointerId)` - binds events with the given `pointerId` to `elem`. After the call all pointer events with the same `pointerId` will have `elem` as the target (as if happened on `elem`), no matter where in document they really happened. -======= -- `elem.setPointerCapture(pointerId)` -- binds events with the given `pointerId` to `elem`. After the call all pointer events with the same `pointerId` will have `elem` as the target (as if happened on `elem`), no matter where in document they really happened. ->>>>>>> upstream/master - -In other words, `elem.setPointerCapture(pointerId)` retargets all subsequent events with the given `pointerId` to `elem`. - -The binding is removed: -- automatically when `pointerup` or `pointercancel` events occur, -- automatically when `elem` is removed from the document, -- when `elem.releasePointerCapture(pointerId)` is called. +이제 실제로 공을 움직이는 코드를 추가할 수 있고, 드래그 앤 드롭이 마우스 기기와 터치 기기에서 모두 동작합니다. -<<<<<<< HEAD -**Pointer capturing can be used to simplify drag'n'drop kind of interactions.** +## 포인터 캡처링 -As an example, let's recall how one can implement a custom slider, described in the . +포인터 캡처링(Pointer capturing)은 포인터 이벤트의 특별한 기능입니다. -We make a slider element with the strip and the "runner" (`thumb`) inside it. +개념은 매우 단순하지만, 다른 이벤트 유형에는 이런 기능이 없어 처음에는 꽤 낯설어 보일 수 있습니다. -Then it works like this: +주요 메서드는 다음과 같습니다. +- `elem.setPointerCapture(pointerId)` -- 지정한 `pointerId`를 가진 이벤트를 `elem`에 바인딩합니다. 호출 이후에는 같은 `pointerId`를 가진 모든 포인터 이벤트가 실제로 문서 어디에서 발생했든 상관없이 `elem`을 타깃으로 갖습니다. 마치 `elem`에서 발생한 것처럼 처리됩니다. -1. The user presses on the slider `thumb` - `pointerdown` triggers. -2. Then they move the pointer - `pointermove` triggers, and we move the `thumb` along. - - ...As the pointer moves, it may leave the slider `thumb`: go above or below it. The `thumb` should move strictly horizontally, remaining aligned with the pointer. +다시 말해 `elem.setPointerCapture(pointerId)`는 이후에 발생하는, 지정한 `pointerId`를 가진 모든 이벤트의 타깃을 `elem`으로 재지정합니다. -So, to track all pointer movements, including when it goes above/below the `thumb`, we had to assign `pointermove` event handler on the whole `document`. +바인딩은 다음과 같은 경우에 해제됩니다. +- `pointerup` 또는 `pointercancel` 이벤트가 발생하면 자동으로 해제됩니다. +- `elem`이 문서에서 제거되면 자동으로 해제됩니다. +- `elem.releasePointerCapture(pointerId)`가 호출되면 해제됩니다. -That solution looks a bit "dirty". One of the problems is that pointer movements around the document may cause side effects, trigger other event handlers, totally not related to the slider. +그렇다면 어디에 유용할까요? 실제 예시를 볼 차례입니다. -Pointer capturing provides a means to bind `pointermove` to `thumb` and avoid any such problems: +**포인터 캡처링은 드래그 앤 드롭 같은 상호작용을 단순화하는 데 사용할 수 있습니다.** -- We can call `thumb.setPointerCapture(event.pointerId)` in `pointerdown` handler, -- Then future pointer events until `pointerup/cancel` will be retargeted to `thumb`. -- When `pointerup` happens (dragging complete), the binding is removed automatically, we don't need to care about it. +에서 설명한 커스텀 슬라이더 구현 방법을 떠올려 봅시다. -So, even if the user moves the pointer around the whole document, events handlers will be called on `thumb`. Besides, coordinate properties of the event objects, such as `clientX/clientY` will still be correct - the capturing only affects `target/currentTarget`. -======= -Now what is it good for? It's time to see a real-life example. - -**Pointer capturing can be used to simplify drag'n'drop kind of interactions.** - -Let's recall how one can implement a custom slider, described in the . - -We can make a `slider` element to represent the strip and the "runner" (`thumb`) inside it: +막대를 나타내는 `slider` 요소와 그 안의 '러너'(`thumb`)를 만들 수 있습니다. ```html
@@ -253,120 +186,97 @@ We can make a `slider` element to represent the strip and the "runner" (`thumb`)
``` -With styles, it looks like this: +스타일을 적용하면 다음과 같습니다. [iframe src="slider-html" height=40 edit]

-And here's the working logic, as it was described, after replacing mouse events with similar pointer events: +마우스 이벤트를 유사한 포인터 이벤트로 바꾼 뒤의 동작 로직은 다음과 같습니다. -1. The user presses on the slider `thumb` -- `pointerdown` triggers. -2. Then they move the pointer -- `pointermove` triggers, and our code moves the `thumb` element along. - - ...As the pointer moves, it may leave the slider `thumb` element, go above or below it. The `thumb` should move strictly horizontally, remaining aligned with the pointer. +1. 사용자가 슬라이더 `thumb`를 누르면 `pointerdown`이 발생합니다. +2. 그런 다음 포인터를 움직이면 `pointermove`가 발생하고, 코드가 `thumb` 요소를 함께 움직입니다. + - ...포인터가 움직이다 보면 슬라이더 `thumb` 요소를 벗어나 위아래로 이동할 수 있습니다. 그래도 `thumb`는 포인터에 맞춰 정확히 수평 방향으로만 이동해야 합니다. -In the mouse event based solution, to track all pointer movements, including when it goes above/below the `thumb`, we had to assign `mousemove` event handler on the whole `document`. +마우스 이벤트 기반 해결책에서는 포인터가 `thumb` 위아래로 이동하는 경우까지 포함해 모든 포인터 움직임을 추적하려고 전체 `document`에 `mousemove` 이벤트 핸들러를 할당해야 했습니다. -That's not a cleanest solution, though. One of the problems is that when a user moves the pointer around the document, it may trigger event handlers (such as `mouseover`) on some other elements, invoke totally unrelated UI functionality, and we don't want that. +하지만 그다지 깔끔한 해결책은 아닙니다. 문제 중 하나는 사용자가 문서 여기저기로 포인터를 움직일 때 다른 요소의 이벤트 핸들러, 예를 들어 `mouseover`를 트리거 해 전혀 관련 없는 UI 기능을 실행할 수 있다는 점입니다. 이는 원하지 않는 동작입니다. -This is the place where `setPointerCapture` comes into play. +이럴 때 `setPointerCapture`가 등장합니다. -- We can call `thumb.setPointerCapture(event.pointerId)` in `pointerdown` handler, -- Then future pointer events until `pointerup/cancel` will be retargeted to `thumb`. -- When `pointerup` happens (dragging complete), the binding is removed automatically, we don't need to care about it. +- `pointerdown` 핸들러에서 `thumb.setPointerCapture(event.pointerId)`를 호출합니다. +- 이후 `pointerup·pointercancel`까지의 포인터 이벤트는 `thumb`로 재지정됩니다. +- `pointerup`이 발생하면, 즉 드래그가 완료되면 바인딩은 자동으로 해제되므로 신경 쓸 필요가 없습니다. -So, even if the user moves the pointer around the whole document, events handlers will be called on `thumb`. Nevertheless, coordinate properties of the event objects, such as `clientX/clientY` will still be correct - the capturing only affects `target/currentTarget`. ->>>>>>> upstream/master +따라서 사용자가 문서 전체에서 포인터를 움직이더라도 이벤트 핸들러는 `thumb`에서 호출됩니다. 그럼에도 `clientX·clientY` 같은 이벤트 객체의 좌표 프로퍼티는 여전히 올바릅니다. 캡처링은 `target·currentTarget`에만 영향을 줍니다. -Here's the essential code: +핵심 코드는 다음과 같습니다. ```js thumb.onpointerdown = function(event) { - // retarget all pointer events (until pointerup) to thumb + // 모든 포인터 이벤트(pointerup까지)를 thumb으로 재지정합니다. thumb.setPointerCapture(event.pointerId); - // start tracking pointer moves + // 포인터 이동 추적을 시작합니다. thumb.onpointermove = function(event) { - // moving the slider: listen on the thumb, as all pointer events are retargeted to it + // 슬라이더 이동: 모든 포인터 이벤트가 thumb으로 재지정되므로 thumb에서 처리합니다. let newLeft = event.clientX - slider.getBoundingClientRect().left; thumb.style.left = newLeft + 'px'; }; - // on pointer up finish tracking pointer moves + // pointerup에서 포인터 이동 추적을 끝냅니다. thumb.onpointerup = function(event) { thumb.onpointermove = null; thumb.onpointerup = null; - // ...also process the "drag end" if needed + // ...필요하다면 "드래그 종료"도 처리합니다. }; }; -<<<<<<< HEAD -thumb.onpointermove = function(event) { - // moving the slider: listen on the thumb, as all pointer events are retargeted to it - let newLeft = event.clientX - slider.getBoundingClientRect().left; - thumb.style.left = newLeft + 'px'; -}; - -// note: no need to call thumb.releasePointerCapture, -======= -// note: no need to call thumb.releasePointerCapture, ->>>>>>> upstream/master -// it happens on pointerup automatically +// thumb.releasePointerCapture를 호출할 필요는 없습니다. +// pointerup에서 자동으로 처리됩니다. ``` ```online -The full demo: +전체 데모입니다. [iframe src="slider" height=100 edit]

-In the demo, there's also an additional element with `onmouseover` handler showing the current date. +데모에는 현재 날짜를 보여주는 `onmouseover` 핸들러가 있는 추가 요소도 있습니다. -Please note: while you're dragging the thumb, you may hover over this element, and its handler *does not* trigger. +thumb을 드래그하는 동안 이 요소 위로 마우스를 올려도 핸들러가 *실행되지 않는다*는 점에 주목하세요. -So the dragging is now free of side effects, thanks to `setPointerCapture`. +`setPointerCapture` 덕분에 이제 드래그에 부작용이 없습니다. ``` -<<<<<<< HEAD -At the end, pointer capturing gives us two benefits: -1. The code becomes cleaner as we don't need to add/remove handlers on the whole `document` any more. The binding is released automatically. -2. If there are any `pointermove` handlers in the document, they won't be accidentally triggered by the pointer while the user is dragging the slider. - -### Pointer capturing events -======= ->>>>>>> upstream/master -At the end, pointer capturing gives us two benefits: -1. The code becomes cleaner as we don't need to add/remove handlers on the whole `document` any more. The binding is released automatically. -2. If there are other pointer event handlers in the document, they won't be accidentally triggered by the pointer while the user is dragging the slider. +결국 포인터 캡처링은 두 가지 이점을 줍니다. +1. 전체 `document`에 핸들러를 추가하거나 제거할 필요가 없어 코드가 더 깔끔해집니다. 바인딩은 자동으로 해제됩니다. +2. 문서에 다른 포인터 이벤트 핸들러가 있어도 사용자가 슬라이더를 드래그하는 동안 포인터 때문에 실수로 트리거 되지 않습니다. -### Pointer capturing events +### 포인터 캡처링 이벤트 -There's one more thing to mention here, for the sake of completeness. +완전성을 위해 한 가지 더 언급하겠습니다. -There are two events associated with pointer capturing: +포인터 캡처링과 관련된 이벤트는 두 가지입니다. -- `gotpointercapture` fires when an element uses `setPointerCapture` to enable capturing. -- `lostpointercapture` fires when the capture is released: either explicitly with `releasePointerCapture` call, or automatically on `pointerup`/`pointercancel`. +- `gotpointercapture`는 요소가 `setPointerCapture`를 사용해 캡처링을 활성화할 때 발생합니다. +- `lostpointercapture`는 캡처가 해제될 때 발생합니다. 해제는 releasePointerCapture를 직접 호출해서 이루어질 수도 있고, `pointerup`·`pointercancel` 시 자동으로 이루어질 수도 있습니다. -## Summary +## 요약 -Pointer events allow handling mouse, touch and pen events simultaneously, with a single piece of code. +포인터 이벤트를 사용하면 하나의 코드로 마우스, 터치, 펜 이벤트를 동시에 처리할 수 있습니다. -Pointer events extend mouse events. We can replace `mouse` with `pointer` in event names and expect our code to continue working for mouse, with better support for other device types. +포인터 이벤트는 마우스 이벤트를 확장합니다. 이벤트 이름에서 `mouse`를 `pointer`로 바꾸어도 마우스에서 계속 동작하며, 다른 기기 유형에 대한 지원도 향상됩니다. -<<<<<<< HEAD -For drag'n'drops and complex touch interactions that the browser may decide to hijack and handle on its own - remember to cancel the default action on events and set `touch-events: none` in CSS for elements that we engage. -======= -For drag'n'drops and complex touch interactions that the browser may decide to hijack and handle on its own - remember to cancel the default action on events and set `touch-action: none` in CSS for elements that we engage. ->>>>>>> upstream/master +브라우저가 가로채서 직접 처리할 수 있는 드래그 앤 드롭과 복잡한 터치 상호작용에서는, 이벤트의 기본 동작을 취소하고 관련 요소에 CSS로 `touch-action: none`을 설정해야 한다는 점을 잊지 마세요. -Additional abilities of pointer events are: +포인터 이벤트의 추가 기능은 다음과 같습니다. -- Multi-touch support using `pointerId` and `isPrimary`. -- Device-specific properties, such as `pressure`, `width/height`, and others. -- Pointer capturing: we can retarget all pointer events to a specific element until `pointerup`/`pointercancel`. +- `pointerId`와 `isPrimary`를 사용한 멀티 터치 지원 +- `pressure`, `width·height` 등 기기별 프로퍼티 +- 포인터 캡처링: `pointerup`·`pointercancel`까지 모든 포인터 이벤트를 특정 요소로 재지정할 수 있습니다. -As of now, pointer events are supported in all major browsers, so we can safely switch to them, especially if IE10- and Safari 12- are not needed. And even with those browsers, there are polyfills that enable the support of pointer events. +현재 포인터 이벤트는 모든 주요 브라우저에서 지원되므로, 특히 IE10 이하와 Safari 12 이하를 지원할 필요가 없다면 안전하게 전환할 수 있습니다. 해당 브라우저에서도 포인터 이벤트 지원을 가능하게 해주는 폴리필이 있습니다. \ No newline at end of file diff --git a/2-ui/3-event-details/7-keyboard-events/article.md b/2-ui/3-event-details/7-keyboard-events/article.md index 12fe632016..b9d4b6d205 100644 --- a/2-ui/3-event-details/7-keyboard-events/article.md +++ b/2-ui/3-event-details/7-keyboard-events/article.md @@ -197,4 +197,4 @@ Main keyboard event properties: In the past, keyboard events were sometimes used to track user input in form fields. That's not reliable, because the input can come from various sources. We have `input` and `change` events to handle any input (covered later in the chapter ). They trigger after any kind of input, including copy-pasting or speech recognition. -We should use keyboard events when we really want keyboard. For example, to react on hotkeys or special keys. +We should use keyboard events when we really want keyboard. For example, to react on hotkeys or special keys. \ No newline at end of file diff --git a/2-ui/3-event-details/8-onscroll/article.md b/2-ui/3-event-details/8-onscroll/article.md index 734bd84c61..520c2e6148 100644 --- a/2-ui/3-event-details/8-onscroll/article.md +++ b/2-ui/3-event-details/8-onscroll/article.md @@ -34,4 +34,4 @@ If we add an event handler to these events and `event.preventDefault()` in it, t There are many ways to initiate a scroll, so it's more reliable to use CSS, `overflow` property. -Here are few tasks that you can solve or look through to see applications of `onscroll`. +Here are few tasks that you can solve or look through to see applications of `onscroll`. \ No newline at end of file diff --git a/2-ui/5-loading/03-onload-onerror/article.md b/2-ui/5-loading/03-onload-onerror/article.md index 590e54ab40..dc5cd20fa4 100644 --- a/2-ui/5-loading/03-onload-onerror/article.md +++ b/2-ui/5-loading/03-onload-onerror/article.md @@ -203,4 +203,4 @@ Images ``, external styles, scripts and other resources provide `load` and The only exception is `