Change Bar hover behaviour, Bar animation

This commit is contained in:
Faris Ansari 2018-02-17 23:23:05 +05:30
parent e55107ee82
commit 390fd2d324
8 changed files with 160 additions and 67 deletions

View File

@ -68,12 +68,16 @@
.gantt .bar-wrapper {
cursor: pointer; }
.gantt .bar-wrapper:hover .bar {
stroke-width: 2; }
fill: #a9b5c1; }
.gantt .bar-wrapper:hover .bar-progress {
fill: #8a8aff; }
.gantt .bar-wrapper:hover .handle {
visibility: visible;
opacity: 1; }
.gantt .bar-wrapper.active .bar {
stroke-width: 2; }
fill: #a9b5c1; }
.gantt .bar-wrapper.active .bar-progress {
fill: #8a8aff; }
.gantt .lower-text, .gantt .upper-text {
font-size: 12px;

120
dist/frappe-gantt.js vendored
View File

@ -245,7 +245,64 @@ function createSVG(tag, attrs) {
return elem;
}
function animateSVG(svgElement, attr, from, to) {
const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);
if (animatedSvgElement === svgElement) {
// triggered 2nd time programmatically
// trigger artificial click event
const event = document.createEvent('HTMLEvents');
event.initEvent('click', true, true);
event.eventName = 'click';
animatedSvgElement.dispatchEvent(event);
}
}
function getAnimationElement(
svgElement,
attr,
from,
to,
dur = '0.4s',
begin = '0.1s'
) {
const animEl = svgElement.querySelector('animate');
if (animEl) {
$.attr(animEl, {
attributeName: attr,
from,
to,
dur,
begin: 'click + ' + begin // artificial click
});
return svgElement;
}
const animateElement = createSVG('animate', {
attributeName: attr,
from,
to,
dur,
begin,
calcMode: 'spline',
values: from + ';' + to,
keyTimes: '0; 1',
keySplines: cubic_bezier('ease-out')
});
svgElement.appendChild(animateElement);
return svgElement;
}
function cubic_bezier(name) {
return {
ease: '.25 .1 .25 1',
linear: '0 0 1 1',
'ease-in': '.42 0 1 1',
'ease-out': '0 0 .58 1',
'ease-in-out': '.42 0 .58 1'
}[name];
}
$.on = (element, event, selector, callback) => {
if (!callback) {
@ -385,6 +442,8 @@ class Bar {
append_to: this.bar_group
});
animateSVG(this.$bar, 'width', 0, this.width);
if (this.invalid) {
this.$bar.classList.add('bar-invalid');
}
@ -402,6 +461,8 @@ class Bar {
class: 'bar-progress',
append_to: this.bar_group
});
animateSVG(this.$bar_progress, 'width', 0, this.progress_width);
}
draw_label() {
@ -412,7 +473,8 @@ class Bar {
class: 'bar-label',
append_to: this.bar_group
});
this.update_label_position();
// labels get BBox in the next tick
requestAnimationFrame(() => this.update_label_position());
}
draw_resize_handles() {
@ -467,27 +529,35 @@ class Bar {
bind() {
if (this.invalid) return;
this.setup_click_event();
this.show_details();
// this.bind_resize_progress();
}
show_details() {
this.group.onclick = e => {
setup_click_event() {
$.on(this.group, 'click', e => {
if (this.action_completed) {
// just finished a move action, wait for a few seconds
return;
}
const start_date = date_utils.format(this.task._start, 'MMM D');
const end_date = date_utils.format(this.task._end, 'MMM D');
const subtitle = start_date + ' - ' + end_date;
if (this.group.classList.contains('active')) {
this.gantt.trigger_event('click', [this.task]);
}
this.gantt.unselect_all();
this.group.classList.toggle('active');
this.gantt.show_popup({
target_element: this.$bar,
title: this.task.name,
subtitle: subtitle
});
};
this.show_popup();
});
}
show_popup() {
const start_date = date_utils.format(this.task._start, 'MMM D');
const end_date = date_utils.format(this.task._end, 'MMM D');
const subtitle = start_date + ' - ' + end_date;
this.gantt.show_popup({
target_element: this.$bar,
title: this.task.name,
subtitle: subtitle
});
}
update_bar_position({ x = null, width = null }) {
@ -517,20 +587,6 @@ class Bar {
// this.update_details_position();
}
setup_click_event() {
this.group.onclick = () => {
if (this.action_completed) {
// just finished a move action, wait for a few seconds
return;
}
if (this.group.classList.contains('active')) {
this.gantt.trigger_event('click', [this.task]);
}
this.gantt.unselect_all();
this.group.classList.toggle('active');
};
}
date_changed() {
const { new_start_date, new_end_date } = this.compute_start_end_date();
this.task._start = new_start_date;
@ -662,6 +718,7 @@ class Bar {
update_label_position() {
const bar = this.$bar,
label = this.group.querySelector('.bar-label');
if (label.getBBox().width > bar.getWidth()) {
label.classList.add('big');
label.setAttribute('x', bar.getX() + bar.getWidth() + 5);
@ -849,6 +906,7 @@ class Popup {
this.pointer.style.top =
this.title.clientHeight / 2 -
this.pointer.getBoundingClientRect().height +
2 +
'px';
}
@ -1421,7 +1479,7 @@ class Gantt {
bind_grid_click() {
this.layers.grid.onclick = () => {
this.unselect_all();
this.popup && this.popup.hide();
this.hide_popup();
};
}
@ -1661,6 +1719,10 @@ class Gantt {
this.popup.show(options);
}
hide_popup() {
this.popup && this.popup.hide();
}
trigger_event(event, args) {
if (this.options['on_' + event]) {
this.options['on_' + event].apply(null, args);

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
import date_utils from './date_utils';
import { createSVG } from './svg_utils';
import { $, createSVG, animateSVG } from './svg_utils';
export default class Bar {
constructor(gantt, task) {
@ -85,6 +85,8 @@ export default class Bar {
append_to: this.bar_group
});
animateSVG(this.$bar, 'width', 0, this.width);
if (this.invalid) {
this.$bar.classList.add('bar-invalid');
}
@ -102,6 +104,8 @@ export default class Bar {
class: 'bar-progress',
append_to: this.bar_group
});
animateSVG(this.$bar_progress, 'width', 0, this.progress_width);
}
draw_label() {
@ -112,7 +116,8 @@ export default class Bar {
class: 'bar-label',
append_to: this.bar_group
});
this.update_label_position();
// labels get BBox in the next tick
requestAnimationFrame(() => this.update_label_position());
}
draw_resize_handles() {
@ -167,27 +172,35 @@ export default class Bar {
bind() {
if (this.invalid) return;
this.setup_click_event();
this.show_details();
// this.bind_resize_progress();
}
show_details() {
this.group.onclick = e => {
setup_click_event() {
$.on(this.group, 'click', e => {
if (this.action_completed) {
// just finished a move action, wait for a few seconds
return;
}
const start_date = date_utils.format(this.task._start, 'MMM D');
const end_date = date_utils.format(this.task._end, 'MMM D');
const subtitle = start_date + ' - ' + end_date;
if (this.group.classList.contains('active')) {
this.gantt.trigger_event('click', [this.task]);
}
this.gantt.unselect_all();
this.group.classList.toggle('active');
this.gantt.show_popup({
target_element: this.$bar,
title: this.task.name,
subtitle: subtitle
});
};
this.show_popup();
});
}
show_popup() {
const start_date = date_utils.format(this.task._start, 'MMM D');
const end_date = date_utils.format(this.task._end, 'MMM D');
const subtitle = start_date + ' - ' + end_date;
this.gantt.show_popup({
target_element: this.$bar,
title: this.task.name,
subtitle: subtitle
});
}
update_bar_position({ x = null, width = null }) {
@ -217,20 +230,6 @@ export default class Bar {
// this.update_details_position();
}
setup_click_event() {
this.group.onclick = () => {
if (this.action_completed) {
// just finished a move action, wait for a few seconds
return;
}
if (this.group.classList.contains('active')) {
this.gantt.trigger_event('click', [this.task]);
}
this.gantt.unselect_all();
this.group.classList.toggle('active');
};
}
date_changed() {
const { new_start_date, new_end_date } = this.compute_start_end_date();
this.task._start = new_start_date;
@ -362,6 +361,7 @@ export default class Bar {
update_label_position() {
const bar = this.$bar,
label = this.group.querySelector('.bar-label');
if (label.getBBox().width > bar.getWidth()) {
label.classList.add('big');
label.setAttribute('x', bar.getX() + bar.getWidth() + 5);

View File

@ -92,7 +92,11 @@ $handle-color: #ddd;
&:hover {
.bar {
stroke-width: 2;
fill: darken($bar-color, 5);
}
.bar-progress {
fill: darken($blue, 5);
}
.handle {
@ -103,7 +107,11 @@ $handle-color: #ddd;
&.active {
.bar {
stroke-width: 2;
fill: darken($bar-color, 5);
}
.bar-progress {
fill: darken($blue, 5);
}
}
}

View File

@ -566,7 +566,7 @@ export default class Gantt {
bind_grid_click() {
this.layers.grid.onclick = () => {
this.unselect_all();
this.popup && this.popup.hide();
this.hide_popup();
};
}
@ -806,6 +806,10 @@ export default class Gantt {
this.popup.show(options);
}
hide_popup() {
this.popup && this.popup.hide();
}
trigger_event(event, args) {
if (this.options['on_' + event]) {
this.options['on_' + event].apply(null, args);

View File

@ -55,6 +55,7 @@ export default class Popup {
this.pointer.style.top =
this.title.clientHeight / 2 -
this.pointer.getBoundingClientRect().height +
2 +
'px';
}

View File

@ -37,8 +37,8 @@ function getAnimationElement(
attr,
from,
to,
dur = '0.3s',
begin = '0s'
dur = '0.4s',
begin = '0.1s'
) {
const animEl = svgElement.querySelector('animate');
if (animEl) {
@ -57,13 +57,27 @@ function getAnimationElement(
from,
to,
dur,
begin
begin,
calcMode: 'spline',
values: from + ';' + to,
keyTimes: '0; 1',
keySplines: cubic_bezier('ease-out')
});
svgElement.appendChild(animateElement);
return svgElement;
}
function cubic_bezier(name) {
return {
ease: '.25 .1 .25 1',
linear: '0 0 1 1',
'ease-in': '.42 0 1 1',
'ease-out': '0 0 .58 1',
'ease-in-out': '.42 0 .58 1'
}[name];
}
$.on = (element, event, selector, callback) => {
if (!callback) {
callback = selector;