# DraggbleManager Information and Demo
In the `src/utils/DraggableManager/demo` folder there is a small project that demonstrates the use of the `DraggableManager` utility.
The demo contains two components:
- `DividerDemo`, which occupies the top half of the web page
- `RegionDemo`, which occupies the bottom half of the web page, as shown in the GIF, below
![GIF of Demo](demo/demo-ux.gif)
## Caveat
This DraggableManager utility does not actually "drag" anything, it does not move or drag DOM elements, it just tells us where the mouse is while the mouse is down. Primarily, it listens for `mousedown` and subsequent `mousemove` and then finally `mouseup` events. (It listens to `window` for the `mousemove` and `mouseup` events.)
What we do with that information is up to us. This is mentioned because you need to handle the DraggableManager callbacks _to create the illusion of dragging_.
## In brief
DraggableManager instances provide three (and a half) conveniences:
- Handle mouse events related to dragging.
- Maps `MouseEvent.clientX` from the [client area](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/clientX) to the local context (yielding `x` (pixels) and `value` (0 -> 1, e.g, `x/width`)).
- Maintains a sense of state in terms of whether or not the subject DOM element is being dragged. For example, it fires `onMouseMove` callbacks when not being dragged and `onDragMove` when being dragged.
- Two other minor conveniences (relating to window events)
And, DraggableManager instances have two (or three) primary requirements:
- Mouse events need to be piped into it
- The `getBounds()` constructor parameter must be provided
- At least some of the callbacks need to be handled
## Conveniences
### Handles the mouse events related to dragging
For the purposes of handling mouse events related to the intended dragging functionality, DraggableManager instances expose the following methods (among others):
- `handleMouseEnter`
- `handleMouseMove`
- `handleMouseLeave`
- `handleMouseDown`
To use a DraggableManager instance, relevant mouse events should be piped to the above handlers:
```jsx
<div className="DividerDemo--realm">
<div className="DividerDemo--divider" onMouseDown={this._dragManager.handleMouseDown} />
</div>
```
> **Note:** Not all handlers are always necessary. See "Mouse events need to be piped into it" for more details.
### Maps the `clientX` to `x` and `value`
`MouseEvent` (and `SyntheticMouseEvent`) events provide the [`clientX`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/clientX) property, which generally needs some adjustments before it's useful. For instance, in the following snippet we transform `clientX` to the `x` within the `<div>`. The `value` is simply the `x/width` ratio, which is pretty much the percent but divided by `100`.
```jsx
<div className="DividerDemo--realm">
<div
className="DividerDemo--divider"
onMouseDown={(event) => {
const { clientX, target } = event;
const { left, width } = target.getBoundingClientRect();
const localX = clientX - left;
console.log('within the client area, x:', clientX);
console.log('within the div, x: ', localX);
console.log('position along the width: ', localX / width);
}}
/>
</div>
```
In other words, DraggableManager instances convert the data to the relevant context. (The "relevant context" is, naturally, varies... see the `getBounds()` constructor parameter below).
### Maintains a sense of state
The callbacks for DraggableManager instances are:
- onMouseEnter
- onMouseLeave
- onMouseMove
- onDragStart
- onDragMove
- onDragEnd
Implicit in the breakdown of the callbacks is the notion that `onDrag*` callbacks are fired when dragging and `onMouse*` callbacks are issued, otherwise.
Therefore, using the DraggableManager util relieves us of the necessity of keeping track of whether we are currently dragging or not.
### Two other minor conveniences
When dragging starts, the util then switches over to listening to window events (`mousemove` and `mouseup`). This prevents the dragging from having strange behavior if / when the user moves the mouse anywhere on the page.
Last but not least...
The util listens for window resize events and makes adjustments accordingly, preventing things from going crazy (due to miscalibration) if the user resizes the window. This primary relates to the `getBounds()` constructor option (see below).
## Requirements
### Mouse events need to be piped into it
In my use, DraggbaleManager instances become the receiver of the relevant mouse events instead of handlers on the React component.
For instance, if implementing a draggable divider (see `DividerDemo.js` and the top half of the gif), only `onMouseDown` needs to be handled:
```jsx
<div className="DividerDemo--realm">
<div className="DividerDemo--divider" onMouseDown={this._dragManager.handleMouseDown} />
</div>
```
But, if implementing the ability to drag a sub-range (see `RegionDemo.js` and the bottom of demo gif), you generally want to show a vertical line at the mouse cursor until the dragging starts (`onMouseDown`), then you want to draw the region being dragged. So, the `onMouseMove`, `onMouseLeave` and `onMouseDown` handlers are necessary:
```jsx
<div
className="RegionDemo--realm"
onMouseDown={this._dragManager.handleMouseDown}
onMouseMove={this._dragManager.handleMouseMove}
onMouseLeave={this._dragManager.handleMouseMove}
>
{/* Draw visuals for the currently dragged range, otherwise empty */}
</div>
```
### `getBounds()` constructor parameter
The crux of the conversion from `clientX` to `x` and `value` is the `getBounds()` constructor parameter.
The function is a required constructor parameter, and it must return a `DraggableBounds` object:
```
type DraggableBounds = {
clientXLeft: number,
maxValue?: number,
minValue?: number,
width: number,
};
```
This generally amounts to calling [`Element#getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) on the DOM element that defines the valid dragging range.
For instance, in the `DividerDemo`, the function used is `DivideDemo#_getDraggingBounds()`:
```ts
_getDraggingBounds = (): DraggableBounds => {
if (!this._realmElm) {
throw new Error('invalid state');
}
const { left: clientXLeft, width } = this._realmElm.getBoundingClientRect();
return {
clientXLeft,
width,
maxValue: 0.98,
minValue: 0.02,
};
};
```
In the snippet above, `this._realmElm` is the `<div>` that fills the green draggable region.
On the other hand, if you need more flexibility, this function can ignore the DOM altogether and do something else entirely. It just needs to return an object with `clientXLeft` and `width` properties, at the minimum.
`maxValue` and `minValue` are optional and will restrict the extent of the dragging. They are in terms of `value`, not `x`.
### The callbacks need to be handled
Last but not least, if the callbacks are ignored, nothing happens.
In the `DividerDemo`, we're only interested in repositioning the divider when it is dragged. We don't care about mouse related callbacks. So, only the drag related callbacks are handled. And, all of the drag callbacks are handled in the same way: we update the position of the divider. Done. See `DividerDemo#_handleDragEvent()`.
In the other scenario, `RegionDemo`, we care about showing the red vertical line for mouse-over. This sort of indicates to the user they can click and drag, and when they drag we want to show a region that spans the current drag. So, we handle the mousemove and mouseleave callbacks along with the drag callbacks.
The `RegionDemo` is a bit more involved, so, to break down how we handle the callbacks... First, we store the following state (in the parent element, incidentally):
- `regionCursor` is where we draw the cursor indicator (a red vertical line, in the demo).
- `regionDragging` represents
没有合适的资源?快使用搜索试试~ 我知道了~
grafana-9.4.3.linux-amd64.tar
需积分: 0 5 下载量 100 浏览量
2023-05-29
08:51:09
上传
评论
收藏 79.9MB GZ 举报
温馨提示
共2000个文件
tsx:2021个
ts:1846个
svg:1680个
grafana-9.4.3.linux-amd64.tar
资源推荐
资源详情
资源评论
收起资源包目录
grafana-9.4.3.linux-amd64.tar (2000个子文件)
grafana.dark.2336ef52b5298cb04209.css 209KB
grafana.light.f8ee15f0a88e16124678.css 209KB
editor.main.css 79KB
timepicker.css 12KB
DividerDemo.css 988B
RegionDemo.css 860B
DraggableManagerDemo.css 806B
weight_height.csv 408KB
ohlc_dogecoin.csv 187KB
gdp_per_capita.csv 4KB
flight_info_by_state.csv 681B
browser_marketshare.csv 355B
js_libraries.csv 179B
population_by_state.csv 138B
dataquery.cue 4KB
panelcfg.cue 3KB
panelcfg.cue 2KB
models.cue 2KB
panelcfg.cue 2KB
panelcfg.cue 2KB
panelcfg.cue 2KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1KB
panelcfg.cue 1013B
panelcfg.cue 1001B
panelcfg.cue 914B
panelcfg.cue 912B
panelcfg.cue 912B
panelcfg.cue 814B
fontawesome-webfont.eot 162KB
grafana-icons.eot 29KB
.eslintrc 64B
airports.geojson 260KB
countries.geojson 250KB
usa-states.geojson 87KB
demo-ux.gif 1.01MB
load_big.gif 3KB
load.gif 723B
.gitignore 8B
gen.go 3KB
grafana 128.39MB
grafana-cli 1.38MB
grafana-server 1.38MB
search.grammar 2KB
ng_alert_notification.html 89KB
alert_notification.html 30KB
alert_notification_example.html 27KB
index-template.html 12KB
signup_started.html 11KB
index.html 11KB
invited_to_org.html 11KB
welcome_on_signup.html 11KB
new_user_invite.html 10KB
reset_password.html 10KB
column_options.html 10KB
alert_tab.html 9KB
axes_editor.html 6KB
axes_editor.html 6KB
tab_display.html 5KB
display_editor.html 4KB
thresholds_form.html 4KB
tab_legend.html 4KB
time_regions_form.html 3KB
tls_auth_settings.html 3KB
editor.html 3KB
reset_password.html 2KB
error-template.html 2KB
swagger.html 2KB
openapi3.html 2KB
tab_series_overrides.html 2KB
error.html 2KB
signup_invited.html 2KB
confirm_modal.html 2KB
edit_org.html 1KB
event_editor.html 1KB
stats.html 1KB
module.html 1016B
styleguide.html 710B
admin_home.html 343B
modal.html 341B
http_settings_next.html 217B
tab_time_regions.html 68B
tab_thresholds.html 64B
query_editor_row.html 57B
defaults.ini 55KB
sample.ini 53KB
background_tease.jpg 173KB
logo.jpg 9KB
tsWorker.js 4.5MB
512.6743f01f38a1921b4ef9.js 3.53MB
Kusto.Language.Bridge.min.js 2.95MB
editor.main.js 2.9MB
9870.2bd5fc18fc0dac8aa2af.js 2.79MB
共 2000 条
- 1
- 2
- 3
- 4
- 5
- 6
- 20
资源评论
烟花雨..
- 粉丝: 69
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功