mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
feat(haptic): adds haptic utils
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
import { Component, Element, Prop, PropDidChange, State } from '@stencil/core';
|
import { Component, Element, Prop, PropDidChange, State } from '@stencil/core';
|
||||||
import { GestureDetail } from '../../index';
|
import { GestureDetail } from '../../index';
|
||||||
import { clamp, reorderArray } from '../../utils/helpers';
|
import { clamp, reorderArray } from '../../utils/helpers';
|
||||||
|
import { hapticSelectionChanged, hapticSelectionEnd, hapticSelectionStart} from '../../utils/haptic';
|
||||||
import { CSS_PROP } from '../animation-controller/constants';
|
import { CSS_PROP } from '../animation-controller/constants';
|
||||||
|
|
||||||
const AUTO_SCROLL_MARGIN = 60;
|
const AUTO_SCROLL_MARGIN = 60;
|
||||||
@ -252,9 +253,7 @@ export class ReorderGroup {
|
|||||||
|
|
||||||
item.classList.add(ITEM_REORDER_SELECTED);
|
item.classList.add(ITEM_REORDER_SELECTED);
|
||||||
|
|
||||||
if ((window as any).TapticEngine) {
|
hapticSelectionStart();
|
||||||
(window as any).TapticEngine.gestureSelectionStart();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDragMove(ev: GestureDetail) {
|
private onDragMove(ev: GestureDetail) {
|
||||||
@ -276,9 +275,7 @@ export class ReorderGroup {
|
|||||||
let fromIndex = indexForItem(selectedItem);
|
let fromIndex = indexForItem(selectedItem);
|
||||||
this.lastToIndex = toIndex;
|
this.lastToIndex = toIndex;
|
||||||
|
|
||||||
if ((window as any).TapticEngine) {
|
hapticSelectionChanged();
|
||||||
(window as any).TapticEngine.gestureSelectionChanged();
|
|
||||||
}
|
|
||||||
this._reorderMove(fromIndex, toIndex);
|
this._reorderMove(fromIndex, toIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,9 +318,7 @@ export class ReorderGroup {
|
|||||||
reorderInactive();
|
reorderInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((window as any).TapticEngine) {
|
hapticSelectionEnd();
|
||||||
(window as any).TapticEngine.gestureSelectionEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private itemIndexForTop(deltaY: number): number {
|
private itemIndexForTop(deltaY: number): number {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Component, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core';
|
import { Component, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core';
|
||||||
import { BooleanInputComponent, GestureDetail } from '../../index';
|
import { BooleanInputComponent, GestureDetail } from '../../index';
|
||||||
|
import { hapticSelection } from '../../utils/haptic';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -19,7 +20,7 @@ export class Toggle implements BooleanInputComponent {
|
|||||||
private labelId: string;
|
private labelId: string;
|
||||||
private styleTmr: any;
|
private styleTmr: any;
|
||||||
private gestureConfig: any;
|
private gestureConfig: any;
|
||||||
private startX: number;
|
private pivotX: number;
|
||||||
|
|
||||||
hasFocus: boolean = false;
|
hasFocus: boolean = false;
|
||||||
|
|
||||||
@ -85,39 +86,30 @@ export class Toggle implements BooleanInputComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onDragStart(detail: GestureDetail) {
|
private onDragStart(detail: GestureDetail) {
|
||||||
this.startX = detail.startX;
|
this.pivotX = detail.currentX;
|
||||||
|
this.activated = true;
|
||||||
this.fireFocus();
|
this.fireFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDragMove(detail: GestureDetail) {
|
private onDragMove(detail: GestureDetail) {
|
||||||
const currentX = detail.currentX;
|
const currentX = detail.currentX;
|
||||||
if (this.checked) {
|
const checked = this.checked;
|
||||||
if (currentX + 15 < this.startX) {
|
if (shouldToggle(checked, currentX - this.pivotX, -15)) {
|
||||||
this.checked = false;
|
this.checked = !checked;
|
||||||
this.activated = true;
|
this.pivotX = currentX;
|
||||||
this.startX = currentX;
|
hapticSelection();
|
||||||
}
|
|
||||||
|
|
||||||
} else if (currentX - 15 > this.startX) {
|
|
||||||
this.checked = true;
|
|
||||||
this.activated = (currentX < this.startX + 5);
|
|
||||||
this.startX = currentX;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDragEnd(detail: GestureDetail) {
|
private onDragEnd(detail: GestureDetail) {
|
||||||
const delta = detail.deltaX;
|
const delta = detail.currentX - this.pivotX;
|
||||||
if (this.checked) {
|
const checked = this.checked;
|
||||||
if (delta < -4) {
|
if (shouldToggle(checked, delta, 4)) {
|
||||||
this.checked = false;
|
this.checked = !checked;
|
||||||
}
|
hapticSelection();
|
||||||
|
|
||||||
} else if (delta > 4) {
|
|
||||||
this.checked = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activated = false;
|
this.activated = false;
|
||||||
this.startX = null;
|
|
||||||
this.fireBlur();
|
this.fireBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,3 +174,15 @@ export class Toggle implements BooleanInputComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldToggle(checked: boolean, deltaX: number, margin: number): boolean {
|
||||||
|
const isRTL = document.dir === 'rtl';
|
||||||
|
|
||||||
|
if (checked) {
|
||||||
|
return (!isRTL && (margin > deltaX)) ||
|
||||||
|
(isRTL && (- margin < deltaX));
|
||||||
|
} else {
|
||||||
|
return (!isRTL && (- margin < deltaX)) ||
|
||||||
|
(isRTL && (margin > deltaX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
56
packages/core/src/utils/haptic.ts
Normal file
56
packages/core/src/utils/haptic.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
const _engine = (window as any).TapticEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check to see if the Haptic Plugin is available
|
||||||
|
* @return {boolean} Returns true or false if the plugin is available
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export function hapticAvailable() {
|
||||||
|
return !!_engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger a selection changed haptic event. Good for one-time events
|
||||||
|
* (not for gestures)
|
||||||
|
*/
|
||||||
|
export function hapticSelection() {
|
||||||
|
_engine && _engine.selection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the haptic engine that a gesture for a selection change is starting.
|
||||||
|
*/
|
||||||
|
export function hapticSelectionStart() {
|
||||||
|
_engine && _engine.gestureSelectionStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the haptic engine that a selection changed during a gesture.
|
||||||
|
*/
|
||||||
|
export function hapticSelectionChanged() {
|
||||||
|
_engine && _engine.gestureSelectionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the haptic engine we are done with a gesture. This needs to be
|
||||||
|
* called lest resources are not properly recycled.
|
||||||
|
*/
|
||||||
|
export function hapticSelectionEnd() {
|
||||||
|
_engine && _engine.gestureSelectionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to indicate success/failure/warning to the user.
|
||||||
|
* options should be of the type `{ type: 'success' }` (or `warning`/`error`)
|
||||||
|
*/
|
||||||
|
export function hapticNotification(options: { type: string }) {
|
||||||
|
_engine && _engine.notification(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this to indicate success/failure/warning to the user.
|
||||||
|
* options should be of the type `{ style: 'light' }` (or `medium`/`heavy`)
|
||||||
|
*/
|
||||||
|
export function hapticImpact(options: { style: string }) {
|
||||||
|
_engine && _engine.impact(options);
|
||||||
|
}
|
Reference in New Issue
Block a user