Better tooltip offset handling (fix #4772) (#4773)

- default offset is now [0, 0]
- both offset.x and offset.y are always honoured
- positive x always move the tooltip on the right
- positive y always move the tooltip on the bottom
This commit is contained in:
Yohan Boniface 2016-08-02 16:51:22 +02:00 committed by Vladimir Agafonkin
parent fc1dc96638
commit e746211be7
4 changed files with 66 additions and 17 deletions

View File

@ -49,7 +49,7 @@
iconSize: [50, 50]
});
L.marker([41.22, 9.48], {icon: icon}).addTo(map).bindTooltip('A div icon tooltip following mouse', {sticky: true, direction: 'auto'});
L.marker([41.23, 9.47], {icon: icon}).addTo(map).bindTooltip('A div icon tooltip');
L.marker([41.23, 9.47], {icon: icon}).addTo(map).bindTooltip('A div icon tooltip with custom offset', {direction: 'top', offset: [-25, -25]});
L.marker([41.23, 9.42], {draggable: true}).addTo(map).bindTooltip('Draggable marker tooltip', {permanent: true, direction: 'auto'});
L.marker([41.19, 9.43]).addTo(map).bindTooltip('Clickable marker tooltip', {permanent: true, interactive: true}).on('click', function () { alert('clicked!'); });

12
dist/leaflet.css vendored
View File

@ -573,6 +573,12 @@
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
@ -589,6 +595,12 @@
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;

View File

@ -82,25 +82,63 @@ describe('Tooltip', function () {
expect(spy.calledOnce).to.be(true);
});
it("can be forced on top direction", function () {
it("honours offset on left direction", function () {
var layer = new L.Marker(center).addTo(map);
var spy = sinon.spy();
layer.on('click', spy);
layer.bindTooltip('A long tooltip that should be displayed on the left', {permanent: true, direction: 'left', interactive: true, offset: [-20, -20]});
expect(map.hasLayer(layer._tooltip)).to.be(true);
happen.at('click', 150, 180);
expect(spy.calledOnce).to.be(false);
happen.at('click', 130, 160);
expect(spy.calledOnce).to.be(true);
});
it("can be forced on top direction", function () {
var layer = L.circleMarker(center).addTo(map);
var spy = sinon.spy();
layer.on('click', spy);
layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'top', interactive: true});
expect(map.hasLayer(layer._tooltip)).to.be(true);
happen.at('click', 200, 170); // Marker is on the map center, which is 400px large.
happen.at('click', 200, 180); // Marker is on the map center, which is 400px large.
expect(spy.calledOnce).to.be(true);
});
it("honours offset on top direction", function () {
var layer = L.circleMarker(center).addTo(map);
var spy = sinon.spy();
layer.on('click', spy);
layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'top', interactive: true, offset: [-20, -20]});
happen.at('click', 200, 180);
expect(spy.calledOnce).to.be(false);
happen.at('click', 180, 150);
expect(spy.calledOnce).to.be(true);
});
it("can be forced on bottom direction", function () {
var layer = new L.Marker(center).addTo(map);
var layer = L.circleMarker(center).addTo(map);
var spy = sinon.spy();
layer.on('click', spy);
layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'bottom', interactive: true});
expect(map.hasLayer(layer._tooltip)).to.be(true);
happen.at('click', 200, 210); // Marker is on the map center, which is 400px large.
happen.at('click', 200, 220); // Marker is on the map center, which is 400px large.
expect(spy.calledOnce).to.be(true);
});
it("honours offset on bottom direction", function () {
var layer = L.circleMarker(center).addTo(map);
var spy = sinon.spy();
layer.on('click', spy);
layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'bottom', interactive: true, offset: [20, 20]});
expect(map.hasLayer(layer._tooltip)).to.be(true);
happen.at('click', 200, 220);
expect(spy.calledOnce).to.be(false);
happen.at('click', 220, 230);
expect(spy.calledOnce).to.be(true);
});

View File

@ -11,9 +11,9 @@
* ```
* Note about tooltip offset. Leaflet takes two options in consideration
* for computing tooltip offseting:
* - the `offset` Tooltip option: it defaults to [6, -6], because the tooltip
* tip is 6px width and height. Remember to change this value if you override
* the tip in CSS.
* - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.
* Add a positive x offset to move the tooltip to the right, and a positive y offset to
* move it to the bottom. Negatives will move to the left and top.
* - the `tooltipAnchor` Icon option: this will only be considered for Marker. You
* should adapt this value if you use a custom icon.
*/
@ -29,10 +29,9 @@ L.Tooltip = L.DivOverlay.extend({
// `Map pane` where the tooltip will be added.
pane: 'tooltipPane',
// @option offset: Point = Point(6, -6)
// The offset of the tooltip position. Update it if you customize the
// tooltip tip in CSS.
offset: [6, -6],
// @option offset: Point = Point(0, 0)
// Optional offset of the tooltip position.
offset: [0, 0],
// @option direction: String = 'auto'
// Direction where to open the tooltip. Possible values are: `right`, `left`,
@ -124,17 +123,17 @@ L.Tooltip = L.DivOverlay.extend({
anchor = this._getAnchor();
if (direction === 'top') {
pos = pos.add(L.point(-tooltipWidth / 2, -tooltipHeight + offset.y + anchor.y));
pos = pos.add(L.point(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y));
} else if (direction === 'bottom') {
pos = pos.subtract(L.point(tooltipWidth / 2, offset.y));
pos = pos.subtract(L.point(tooltipWidth / 2 - offset.x, -offset.y));
} else if (direction === 'center') {
pos = pos.subtract(L.point(tooltipWidth / 2, tooltipHeight / 2 - anchor.y));
pos = pos.subtract(L.point(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y));
} else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) {
direction = 'right';
pos = pos.add([offset.x + anchor.x, anchor.y - tooltipHeight / 2]);
pos = pos.add([offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y]);
} else {
direction = 'left';
pos = pos.subtract(L.point(offset.x + tooltipWidth + anchor.x, tooltipHeight / 2 - anchor.y));
pos = pos.subtract(L.point(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y));
}
L.DomUtil.removeClass(container, 'leaflet-tooltip-right');