fix(slide-toggle): occasional element jumping (#3311)

This commit is contained in:
Paul Gschwendtner
2017-03-01 19:48:09 +01:00
committed by Kara
parent 09c6386790
commit beb0edf8f3
3 changed files with 59 additions and 62 deletions
+19 -16
View File
@@ -1,21 +1,6 @@
<label class="mat-slide-toggle-label" #label>
<div class="mat-slide-toggle-container">
<div class="mat-slide-toggle-bar"></div>
<div class="mat-slide-toggle-thumb-container"
(slidestart)="_onDragStart()"
(slide)="_onDrag($event)"
(slideend)="_onDragEnd()">
<div class="mat-slide-toggle-thumb">
<div class="mat-slide-toggle-ripple" md-ripple
[mdRippleTrigger]="label"
[mdRippleCentered]="true"
[mdRippleDisabled]="disableRipple || disabled">
</div>
</div>
</div>
<div class="mat-slide-toggle-bar">
<input #input class="mat-slide-toggle-input cdk-visually-hidden" type="checkbox"
[id]="inputId"
@@ -30,7 +15,25 @@
(focus)="_onInputFocus()"
(change)="_onChangeEvent($event)"
(click)="_onInputClick($event)">
<div class="mat-slide-toggle-thumb-container"
(slidestart)="_onDragStart()"
(slide)="_onDrag($event)"
(slideend)="_onDragEnd()">
<div class="mat-slide-toggle-thumb"></div>
<div class="mat-slide-toggle-ripple" md-ripple
[mdRippleTrigger]="label"
[mdRippleCentered]="true"
[mdRippleDisabled]="disableRipple || disabled">
</div>
</div>
</div>
<span class="mat-slide-toggle-content">
<ng-content></ng-content>
</span>
+33 -41
View File
@@ -3,14 +3,15 @@
@import '../core/style/elevation';
@import '../core/a11y/a11y';
$mat-slide-toggle-width: 36px !default;
$mat-slide-toggle-height: 24px !default;
$mat-slide-toggle-bar-height: 14px !default;
$mat-slide-toggle-thumb-size: 20px !default;
$mat-slide-toggle-bar-border-radius: 8px !default;
$mat-slide-toggle-height: 24px !default;
$mat-slide-toggle-margin: 16px !default;
$mat-slide-toggle-spacing: 8px !default;
$mat-slide-toggle-ripple-radius: 23px !default;
$mat-slide-toggle-bar-width: 36px !default;
$mat-slide-toggle-bar-height: 14px !default;
$mat-slide-toggle-bar-track-width: $mat-slide-toggle-bar-width - $mat-slide-toggle-thumb-size;
.mat-slide-toggle {
@@ -30,13 +31,12 @@ $mat-slide-toggle-ripple-radius: 23px !default;
&.mat-checked {
.mat-slide-toggle-thumb-container {
transform: translate3d(100%, 0, 0);
transform: translate3d($mat-slide-toggle-bar-track-width, 0, 0);
}
}
&.mat-disabled {
.mat-slide-toggle-label, .mat-slide-toggle-container {
.mat-slide-toggle-label, .mat-slide-toggle-thumb-container {
cursor: default;
}
}
@@ -55,6 +55,8 @@ $mat-slide-toggle-ripple-radius: 23px !default;
.mat-slide-toggle-label {
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
cursor: pointer;
}
@@ -62,47 +64,44 @@ $mat-slide-toggle-ripple-radius: 23px !default;
/* If the label should be placed before the thumb then we just change the orders. */
.mat-slide-toggle-label-before {
.mat-slide-toggle-label { order: 1; }
.mat-slide-toggle-container { order: 2; }
.mat-slide-toggle-bar { order: 2; }
}
// Container for the composition of the slide-toggle / switch indicator.
.mat-slide-toggle-container {
cursor: grab;
width: $mat-slide-toggle-width;
height: $mat-slide-toggle-height;
position: relative;
}
/* Apply the margin for slide-toggles and revert it for RTL toggles with labelPosition before. */
[dir='rtl'] .mat-slide-toggle-label-before .mat-slide-toggle-container, .mat-slide-toggle-container {
// Apply the margin for slide-toggles and revert it for RTL toggles with labelPosition before.
[dir='rtl'] .mat-slide-toggle-label-before .mat-slide-toggle-bar,
.mat-slide-toggle-bar {
margin-right: $mat-slide-toggle-spacing;
margin-left: 0;
}
/* Switch the margins in RTL mode and also switch it if the labelPosition is set to before. */
[dir='rtl'], .mat-slide-toggle-label-before {
.mat-slide-toggle-container {
// Switch the margins in RTL mode and also switch it if the labelPosition is set to before.
[dir='rtl'],
.mat-slide-toggle-label-before {
.mat-slide-toggle-bar {
margin-left: $mat-slide-toggle-spacing;
margin-right: 0;
}
}
// The thumb container is responsible for the dragging functionality.
// It moves around and holds the actual circle as a thumb.
// The container includes the visual thumb and the ripple container element.
.mat-slide-toggle-thumb-container {
$thumb-bar-vertical-padding: ($mat-slide-toggle-thumb-size - $mat-slide-toggle-bar-height) / 2;
position: absolute;
top: $mat-slide-toggle-height / 2 - $mat-slide-toggle-thumb-size / 2;
left: 0;
z-index: 1;
width: $mat-slide-toggle-width - $mat-slide-toggle-thumb-size;
width: $mat-slide-toggle-thumb-size;
height: $mat-slide-toggle-thumb-size;
top: -$thumb-bar-vertical-padding;
left: 0;
transform: translate3d(0, 0, 0);
transition: $swift-linear;
transition-property: transform;
cursor: grab;
// Once the thumb container is being dragged around, we remove the transition duration to
// make the drag feeling fast and not delayed.
&.mat-dragging {
@@ -110,14 +109,9 @@ $mat-slide-toggle-ripple-radius: 23px !default;
}
}
// The thumb will be elevated from the slide-toggle bar.
// Also the thumb is bound to its parent thumb-container, which manages the movement of the thumb.
// The visual thumb element that moves inside of the thumb bar.
// The parent thumb-container container is responsible for the movement of the visual thumb.
.mat-slide-toggle-thumb {
position: absolute;
margin: 0;
left: 0;
top: 0;
height: $mat-slide-toggle-thumb-size;
width: $mat-slide-toggle-thumb-size;
border-radius: 50%;
@@ -131,16 +125,14 @@ $mat-slide-toggle-ripple-radius: 23px !default;
}
// Horizontal bar for the slide-toggle.
// The slide-toggle bar is shown behind the thumb container.
// The slide-toggle bar is shown behind the movable thumb element.
.mat-slide-toggle-bar {
position: absolute;
left: 1px;
top: $mat-slide-toggle-height / 2 - $mat-slide-toggle-bar-height / 2;
position: relative;
width: $mat-slide-toggle-width - 2px;
width: $mat-slide-toggle-bar-width;
height: $mat-slide-toggle-bar-height;
border-radius: 8px;
border-radius: $mat-slide-toggle-bar-border-radius;
@include cdk-high-contrast {
background: #fff;
@@ -173,4 +165,4 @@ $mat-slide-toggle-ripple-radius: 23px !default;
border-radius: 50%;
z-index: 1;
pointer-events: none;
}
}
+7 -5
View File
@@ -296,7 +296,7 @@ class SlideToggleRenderer {
/** Previous checked state before drag started. */
private _previousChecked: boolean;
/** Percentage of the thumb while dragging. */
/** Percentage of the thumb while dragging. Percentage as fraction of 100. */
dragPercentage: number;
/** Whether the thumb is currently being dragged. */
@@ -333,12 +333,14 @@ class SlideToggleRenderer {
/** Updates the thumb containers position from the specified distance. */
updateThumbPosition(distance: number) {
this.dragPercentage = this._getThumbPercentage(distance);
applyCssTransform(this._thumbEl, `translate3d(${this.dragPercentage}%, 0, 0)`);
this.dragPercentage = this._getDragPercentage(distance);
// Calculate the moved distance based on the thumb bar width.
let dragX = (this.dragPercentage / 100) * this._thumbBarWidth;
applyCssTransform(this._thumbEl, `translate3d(${dragX}px, 0, 0)`);
}
/** Retrieves the percentage of thumb from the moved distance. */
private _getThumbPercentage(distance: number) {
/** Retrieves the percentage of thumb from the moved distance. Percentage as fraction of 100. */
private _getDragPercentage(distance: number) {
let percentage = (distance / this._thumbBarWidth) * 100;
// When the toggle was initially checked, then we have to start the drag at the end.