Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotation labels #719

Merged
merged 13 commits into from
Jul 26, 2017
184 changes: 132 additions & 52 deletions examples/annotations/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ block append mainContent
.form-group(title='If enabled, immediately after adding one annotation, you can add another without either left-clicking or selecting a button.')
label(for='keepadding') Keep adding annotations
input#keepadding(param-name='keepadding', type='checkbox', placeholder='false')
.form-group(title='If disabled, hide all annotation labels.')
label(for='showLabels') Show annotation labels
input#showLabels(param-name='labels', type='checkbox', placeholder='true')
.form-group#annotationheader
.shortlabel Created Annotations
a.entry-remove-all(action='remove-all', title='Delete all annotations') ✖
Expand All @@ -41,58 +44,135 @@ block append mainContent
button.close(type='button', data-dismiss='modal') ×
h4.modal-title Edit Annotation
.modal-body
.form-group
label(for='edit-name') Name
input#edit-name(option='name')
.form-group(annotation-types='point')
label(for='edit-radius') Radius
input#edit-radius(option='radius', format='positive')
.form-group(annotation-types='point', title='Set to "false" to disable, "true" to use the specified radius at the current zoom, or a zoom level to use the specified radius at that zoom level.')
label(for='edit-scaled') Scale with Zoom
input#edit-radius(option='scaled', format='booleanOrNumber')
.form-group(annotation-types='point polygon rectangle')
label(for='edit-fill') Fill
select#edit-stroke(option='fill', format='boolean')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='point polygon rectangle')
label(for='edit-fillColor') Fill Color
input#edit-fillColor(option='fillColor', format='color')
.form-group(annotation-types='point polygon rectangle')
label(for='edit-fillOpacity') Fill Opacity
input#edit-fillOpacity(option='fillOpacity', format='opacity')
.form-group(annotation-types='point polygon rectangle')
label(for='edit-stroke') Stroke
select#edit-stroke(option='stroke', format='boolean')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='point polygon rectangle line')
label(for='edit-strokeWidth') Stroke Width
input#edit-strokeWidth(option='strokeWidth', format='positive')
.form-group(annotation-types='point polygon rectangle line')
label(for='edit-strokeColor') Stroke Color
input#edit-strokeColor(option='strokeColor', format='color')
.form-group(annotation-types='point polygon rectangle line')
label(for='edit-strokeOpacity') Stroke Opacity
input#edit-strokeOpacity(option='strokeOpacity', format='opacity')
.form-group(annotation-types='line')
label(for='edit-closed') Closed
select#edit-closed(option='closed', format='boolean')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='line')
label(for='edit-lineCap') Line End Caps
select#edit-lineCap(option='lineCap', format='text')
option(value='butt') Butt
option(value='round') Round
option(value='square') Square
.form-group(annotation-types='line')
label(for='edit-lineJoin') Line Joins
select#edit-lineJoin(option='lineJoin', format='text')
option(value='miter') Miter
option(value='bevel') Bevel
option(value='round') Round
option(value='miter-clip') Miter-Clip
.row
.col-md-6
.form-group
label(for='edit-name') Name
input#edit-name(option='name')
.form-group
label(for='edit-description') Description
input#edit-description(option='description', type='textarea')
.form-group(annotation-types='point')
label(for='edit-radius') Radius
input#edit-radius(option='radius', format='positive')
.form-group(annotation-types='point', title='Set to "false" to disable, "true" to use the specified radius at the current zoom, or a zoom level to use the specified radius at that zoom level.')
label(for='edit-scaled') Scale with Zoom
input#edit-radius(option='scaled', format='booleanOrNumber')
.form-group(annotation-types='point polygon rectangle')
label(for='edit-fill') Fill
select#edit-stroke(option='fill', format='boolean')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='point polygon rectangle')
label(for='edit-fillColor') Fill Color
input#edit-fillColor(option='fillColor', format='color')
.form-group(annotation-types='point polygon rectangle')
label(for='edit-fillOpacity') Fill Opacity
input#edit-fillOpacity(option='fillOpacity', format='opacity')
.form-group(annotation-types='point polygon rectangle')
label(for='edit-stroke') Stroke
select#edit-stroke(option='stroke', format='boolean')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='point polygon rectangle line')
label(for='edit-strokeWidth') Stroke Width
input#edit-strokeWidth(option='strokeWidth', format='positive')
.form-group(annotation-types='point polygon rectangle line')
label(for='edit-strokeColor') Stroke Color
input#edit-strokeColor(option='strokeColor', format='color')
.form-group(annotation-types='point polygon rectangle line')
label(for='edit-strokeOpacity') Stroke Opacity
input#edit-strokeOpacity(option='strokeOpacity', format='opacity')
.form-group(annotation-types='line')
label(for='edit-closed') Closed
select#edit-closed(option='closed', format='boolean')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='line')
label(for='edit-lineCap') Line End Caps
select#edit-lineCap(option='lineCap', format='text')
option(value='butt') Butt
option(value='round') Round
option(value='square') Square
.form-group(annotation-types='line')
label(for='edit-lineJoin') Line Joins
select#edit-lineJoin(option='lineJoin', format='text')
option(value='miter') Miter
option(value='bevel') Bevel
option(value='round') Round
option(value='miter-clip') Miter-Clip
.col-md-6
//- label
.form-group(title='The label defaults to the annotation name')
label(for='edit-label') Label
input#edit-label(option='label')
.form-group(annotation-types='all', title='The label will only be shown if both this and the global option are selected')
label(for='edit-showLabel') Show Label
select#edit-showLabel(option='showLabel', format='boolean', optiontype='option')
option(value='true') Yes
option(value='false') No
.form-group(annotation-types='all', title='This is of the form [italic|oblique] [small-caps] [bold|bolder|lighter|<weight>] [<stretch>] <size>[/<line height>] <family>')
label(for='edit-font') Font
input#edit-font(option='font', optiontype='label')
.form-group(annotation-types='all', title='This applies to both the filled text and the stroke')
label(for='edit-textOpacity') Label Opacity
input#edit-textOpacity(option='textOpacity', format='opacity', optiontype='label')
.form-group(annotation-types='all', title='The color of the filled text. Use an rgba() form to specify opacity.')
label(for='edit-color') Fill Color
input#edit-color(option='color', format='color', optiontype='label')
.form-group(annotation-types='all', title='The color of a stroke around the text. If used with Fill Color, this adds a perimeter half the Stroke Width outside of the text. Use an rgba() form to specify opacity.')
label(for='edit-textStrokeColor') Stroke Color
input#edit-textStrokeColor(option='textStrokeColor', format='textStrokeColor', optiontype='label')
.form-group(annotation-types='all')
label(for='edit-textStrokeWidth') Stroke Width
input#edit-textStrokeWidth(option='textStrokeWidth', format='numberOrBlank', optiontype='label')
//- positioning
.form-group(annotation-types='all', title='Horizontal alignment')
label(for='edit-textAlign') Horizontal Align.
select#edit-textAlign(option='textAlign', format='text', optiontype='label')
option(value='center') Center
option(value='start') Start
option(value='end') End
option(value='left') Left
option(value='right') Right
.form-group(annotation-types='all', title='Vertical alignment')
label(for='edit-textBaseline') Vertical Align.
select#edit-textAlign(option='textBaseline', format='text', optiontype='label')
option(value='middle') Middle
option(value='top') Top
option(value='hanging') Hanging
option(value='alphabetic') Alphabetic
option(value='ideographic') Ideographic
option(value='bottom') Bottom
.form-group(annotation-types='all')
label(for='edit-rotateWithMap') Rotate with Map
select#edit-rotateWithMap(option='rotateWithMap', format='boolean', optiontype='label')
option(value='false') No
option(value='true') Yes
.form-group(annotation-types='all')
label(for='edit-rotation') Rotation
input#edit-rotation(option='rotation', format='angle', optiontype='label')
.form-group(annotation-types='all', title='Set to "false" to disable, "true" to use the specified font size at the current zoom, or a zoom level to use the specified font size at that zoom level.')
label(for='edit-textScaled') Base Scale
input#edit-textScaled(option='textScaled', format='booleanOrNumber', optiontype='label')
.form-group(annotation-types='all', title='This is the x, y offset of the label in pixels from its default position before rotation and scale. Example: "5, -4"')
label(for='edit-offset') Offset
input#edit-offset(option='offset', format='coordinate2', optiontype='label')
//- shadow options
.form-group(annotation-types='all')
label(for='edit-shadowColor') Shadow Color
input#edit-shadowColor(option='shadowColor', format='shadowColor', optiontype='label')
.form-group(annotation-types='all')
label(for='edit-shadowBlur') Shadow Blur
input#edit-shadowBlur(option='shadowBlur', format='numberOrBlank', optiontype='label')
.form-group(annotation-types='all', title='This is the x, y shadowOffset of the shadow in pixels from its default position before rotation. Example: "5, -4"')
label(for='edit-shadowOffset') Shadow Offset
input#edit-shadowOffset(option='shadowOffset', format='coordinate2', optiontype='label')
.form-group(annotation-types='all', title='Enable to rotate the shadow absed on the label\'s rotation.')
label(for='edit-shadowRotate') Rotate Shadow
select#edit-shadowRotate(option='shadowRotate', format='boolean', optiontype='label')
option(value='false') No
option(value='true') Yes
.form-group
#edit-validation-error
.modal-footer
Expand Down
2 changes: 1 addition & 1 deletion examples/annotations/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
position: absolute;
left: 10px;
top: 80px;
z-index: 1;
z-index: 1000;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might know the answer..but any more insight on why this change might be useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When layers are children of other layers, we set a z-index on them. When we have multiple layers, this conflicts with the z-index context of the controls. The easy solution is to move the controls to an arbitrary high z-index. It might be better to ensure that the map is a stacking context, which on some browsers would be adding css isolation: isolate, but that doesn't work everywhere and other methods of creating a stacking context involve altering css properties on the map div which might be undesirable in general (we could do so in the examples, though).

border-radius: 5px;
border: 1px solid grey;
box-shadow: 1px 1px 3px black;
Expand Down
101 changes: 87 additions & 14 deletions examples/annotations/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ $(function () {
var query = utils.getQuery();
$('#clickadd').prop('checked', query.clickadd !== 'false');
$('#keepadding').prop('checked', query.keepadding === 'true');
$('#showLabels').prop('checked', query.labels !== 'false');
if (query.lastannotation) {
$('.annotationtype button').removeClass('lastused');
$('.annotationtype button#' + query.lastannotation).addClass('lastused');
Expand Down Expand Up @@ -52,7 +53,8 @@ $(function () {
// create an annotation layer
layer = map.createLayer('annotation', {
renderer: query.renderer ? (query.renderer === 'html' ? null : query.renderer) : undefined,
annotations: query.renderer ? undefined : geo.listAnnotations()
annotations: query.renderer ? undefined : geo.listAnnotations(),
showLabels: query.labels !== 'false'
});
// bind to the mouse click and annotation mode events
layer.geoOn(geo.event.mouseclick, mouseClickToStart);
Expand Down Expand Up @@ -122,6 +124,12 @@ $(function () {
if (!param || value === query[param]) {
return;
}
switch (param) {
case 'labels':
layer.options('showLabels', '' + value !== 'false');
layer.draw();
break;
}
query[param] = value;
if (value === '' || (ctl.attr('placeholder') &&
value === ctl.attr('placeholder'))) {
Expand Down Expand Up @@ -291,14 +299,16 @@ $(function () {
function show_edit_dialog(id) {
var annotation = layer.annotationById(id),
type = annotation.type(),
typeMatch = new RegExp('(^| )' + type + '( |$)'),
typeMatch = new RegExp('(^| )(' + type + '|all)( |$)'),
opt = annotation.options(),
dlg = $('#editdialog');

$('#edit-validation-error', dlg).text('');
dlg.attr('annotation-id', id);
dlg.attr('annotation-type', type);
$('[option="name"]', dlg).val(annotation.name());
$('[option="label"]', dlg).val(annotation.label(undefined, true));
$('[option="description"]', dlg).val(annotation.description());
// populate each control with the current value of the annotation
$('.form-group[annotation-types]').each(function () {
var ctl = $(this),
Expand All @@ -312,14 +322,36 @@ $(function () {
return;
}
ctl.show();
value = opt.style[key];
switch ($('[option]', ctl).attr('optiontype')) {
case 'option':
value = opt[key];
break;
case 'label':
value = (opt.labelStyle || {})[key];
break;
default:
value = opt.style[key];
break;
}
switch (format) {
case 'angle':
if (value !== undefined && value !== null && value !== '') {
value = '' + +(+value * 180.0 / Math.PI).toFixed(4) + ' deg';
}
break;
case 'color':
// always show colors as hex values
value = geo.util.convertColorToHex(value);
value = geo.util.convertColorToHex(value || {r: 0, g: 0, b: 0}, 'needed');
break;
case 'coordinate2':
if (value !== undefined && value !== null && value !== '') {
value = '' + value.x + ', ' + value.y;
}
}
if ((value === undefined || value === '' || value === null) && $('[option]', ctl).is('select')) {
value = $('[option] option', ctl).eq(0).val();
}
$('[option]', ctl).val('' + value);
$('[option]', ctl).val(value === undefined ? '' : '' + value);
});
dlg.one('shown.bs.modal', function () {
$('[option="name"]', dlg).focus();
Expand All @@ -337,33 +369,74 @@ $(function () {
var dlg = $('#editdialog'),
id = dlg.attr('annotation-id'),
annotation = layer.annotationById(id),
opt = annotation.options(),
type = annotation.type(),
typeMatch = new RegExp('(^| )' + type + '( |$)'),
error,
newopt = {};
typeMatch = new RegExp('(^| )(' + type + '|all)( |$)'),
newopt = {style: {}, labelStyle: {}},
error;

// validate form values
$('.form-group[annotation-types]').each(function () {
var ctl = $(this),
key = $('[option]', ctl).attr('option'),
value;
format = $('[option]', ctl).attr('format'),
value, oldvalue;
if (!ctl.attr('annotation-types').match(typeMatch)) {
return;
}
value = layer.validateAttribute($('[option]', ctl).val(),
$('[option]', ctl).attr('format'));
if (value === undefined) {
value = $('[option]', ctl).val();
switch (format) {
case 'angle':
if (/^\s*[.0-9eE]+\s*$/.exec(value)) {
value += 'deg';
}
break;
}
switch (key) {
case 'textScaled':
if (['true', 'on', 'yes'].indexOf(value.trim().toLowerCase()) >= 0) {
value = map.zoom();
}
break;
}
value = layer.validateAttribute(value, format);
switch ($('[option]', ctl).attr('optiontype')) {
case 'option':
oldvalue = opt[key];
break;
case 'label':
oldvalue = (opt.labelStyle || {})[key];
break;
default:
oldvalue = opt.style[key];
break;
}
if (value === oldvalue || (oldvalue === undefined && value === '')) {
// don't change anything
} else if (value === undefined) {
error = $('label', ctl).text() + ' is not a valid value';
} else {
newopt[key] = value;
switch ($('[option]', ctl).attr('optiontype')) {
case 'option':
newopt[key] = value;
break;
case 'label':
newopt.labelStyle[key] = value;
break;
default:
newopt.style[key] = value;
break;
}
}
});
if (error) {
$('#edit-validation-error', dlg).text(error);
return;
}
annotation.name($('[option="name"]', dlg).val());
annotation.options({style: newopt}).draw();
annotation.label($('[option="label"]', dlg).val() || null);
annotation.description($('[option="description"]', dlg).val() || '');
annotation.options(newopt).draw();

dlg.modal('hide');
// refresh the annotation list
Expand Down
Loading