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

Multi export #314

Merged
merged 110 commits into from
Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from 94 commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
f68eae1
sdf
sashadev-sky Jun 15, 2019
63f0cc1
fix conflicts
sashadev-sky Jun 27, 2019
d547fd3
sdfgh
sashadev-sky May 30, 2019
f8a34e5
startExport
sashadev-sky May 30, 2019
f3c75ae
save changes
sashadev-sky May 31, 2019
6d7031a
update ajax
sashadev-sky Jun 4, 2019
15255ca
update url
sashadev-sky Jun 5, 2019
de57f24
sdf
sashadev-sky Jun 6, 2019
f802c00
startexport
sashadev-sky Jun 13, 2019
026f30c
add node modules
sashadev-sky Jun 13, 2019
0c702ee
add nojekyll
sashadev-sky Jun 13, 2019
dd79647
remove node-pre-gyp
sashadev-sky Jun 13, 2019
df6f545
Create CNAME
sashadev-sky Jun 13, 2019
6149919
just images
sashadev-sky Jun 13, 2019
d24e8b2
make it work
sashadev-sky Jun 13, 2019
a600f3d
set data
sashadev-sky Jun 24, 2019
9d711c7
Set url
sashadev-sky Jun 24, 2019
d570fb0
separate out
sashadev-sky Jun 24, 2019
5035bbc
separate out
sashadev-sky Jun 24, 2019
e2e22b8
update all funcs
sashadev-sky Jun 27, 2019
85ff593
make func
sashadev-sky Jun 27, 2019
df2dd04
add source maps
sashadev-sky Jun 27, 2019
670f519
done
sashadev-sky Jun 27, 2019
b0030bc
readd generate export json
sashadev-sky Jun 27, 2019
6319b39
geenerate
sashadev-sky Jun 27, 2019
f3244b1
try remove scale
sashadev-sky Jun 27, 2019
2255c7c
stop stringifying
sashadev-sky Jun 27, 2019
a3dfb78
add a someSelected method
sashadev-sky Jun 27, 2019
6208d14
fix rebase
sashadev-sky Jun 27, 2019
5a75e59
node_modules
sashadev-sky Jun 27, 2019
a0fc1c7
add node modules
sashadev-sky Jun 27, 2019
4ce1279
add 1st collection tool
sashadev-sky Jun 27, 2019
980a52c
allow switchoff
sashadev-sky Jun 27, 2019
3fd5e37
switchoff deselect
sashadev-sky Jun 27, 2019
05f4044
fix updateToolbarPos bug
sashadev-sky Jun 27, 2019
d3ef630
fix markers
sashadev-sky Jun 27, 2019
151f60e
complete collection tool UI
sashadev-sky Jun 27, 2019
a76c23b
failing tests
sashadev-sky Jun 27, 2019
2f83b3a
resolve testing issue
sashadev-sky Jun 27, 2019
c95bba1
repair broken tests
sashadev-sky Jun 27, 2019
341e0af
fix up tests
sashadev-sky Jun 27, 2019
f0b34ef
push to demo
sashadev-sky Jun 27, 2019
9dde10f
again
sashadev-sky Jun 27, 2019
5eb8992
Multi-tool interface
sashadev-sky Jun 27, 2019
bc2c564
Multiple Image Delete
sashadev-sky Jun 27, 2019
85bc31c
refine
sashadev-sky Jun 27, 2019
9dc1aae
doc updates
sashadev-sky Jun 27, 2019
f73ccbe
update
sashadev-sky Jun 28, 2019
06d07a0
update
sashadev-sky Jun 28, 2019
3d834ae
fix deletion bug
sashadev-sky Jun 28, 2019
955723e
UI bug free
sashadev-sky Jun 28, 2019
e2c6148
readme
sashadev-sky Jun 28, 2019
336640a
readme
sashadev-sky Jun 28, 2019
22cc2c0
fix
sashadev-sky Jun 28, 2019
1b47544
allow pic and choose tools
sashadev-sky Jun 28, 2019
c616568
new actions option
sashadev-sky Jun 28, 2019
e0fb14d
upgrade toolbar dependency
sashadev-sky Jun 29, 2019
b0696ce
dependency update
sashadev-sky Jun 29, 2019
345d9f7
Fix tests and file organization
sashadev-sky Jun 29, 2019
efc9e99
add removeTool
sashadev-sky Jun 29, 2019
b45ff76
document removeTool
sashadev-sky Jun 29, 2019
f655a53
document addTool and hasTool
sashadev-sky Jun 29, 2019
04eaff7
remove useless window
sashadev-sky Jun 29, 2019
700bbf1
set keymappers to false until bugs are cleaned
sashadev-sky Jun 29, 2019
605b1a7
expose setCorner
sashadev-sky Jun 29, 2019
b6abc55
remove concat from Gruntfile
sashadev-sky Jun 29, 2019
7adee15
checkout node_modules
sashadev-sky Jun 29, 2019
0ab35b2
Delete CNAME
sashadev-sky Jun 29, 2019
fef61e1
Delete .nojekyll
sashadev-sky Jun 29, 2019
38406df
remove svg bubbles
sashadev-sky Jun 29, 2019
db015b0
Delete leaflet.distortableimage.js.map
sashadev-sky Jun 29, 2019
fabfb00
ignore all committed node_modules
sashadev-sky Jun 29, 2019
bb100be
Merge branch 'multiExport' of https://github.com/sashadev-sky/Leaflet…
sashadev-sky Jun 29, 2019
789d87a
index on multiExport: bb100be3 Merge branch 'multiExport' of https://…
sashadev-sky Jun 29, 2019
7b07d08
WIP on multiExport: bb100be3 Merge branch 'multiExport' of https://gi…
sashadev-sky Jun 29, 2019
811748a
toolbar anchor 10
sashadev-sky Jun 30, 2019
b793851
cleanup
sashadev-sky Jun 30, 2019
e294a9c
doc
sashadev-sky Jun 30, 2019
fc031a8
docs
sashadev-sky Jun 30, 2019
9f7b064
remove concat from gruntfile
sashadev-sky Jun 30, 2019
f966e45
add underscore
sashadev-sky Jun 30, 2019
0d5b8e6
unexpose setCorners() until testing
sashadev-sky Jun 30, 2019
1f3cc73
add tests for multiple image deletion
sashadev-sky Jun 30, 2019
a1da421
add tests for _addToolbar
sashadev-sky Jun 30, 2019
954ad90
uncomment
sashadev-sky Jun 30, 2019
1804662
add removeTb tests
sashadev-sky Jun 30, 2019
769ada6
finish toolbar tests
sashadev-sky Jun 30, 2019
19735b3
comment for modes
sashadev-sky Jul 1, 2019
1bc5ec8
add new line to new files
sashadev-sky Jul 1, 2019
a5a83ac
BoxSelector fixed
sashadev-sky Jul 1, 2019
ccbb8d6
update docs
sashadev-sky Jul 1, 2019
659013b
refactor
sashadev-sky Jul 1, 2019
9fdadfc
refactor
sashadev-sky Jul 1, 2019
912d763
defer some scripts
sashadev-sky Jul 1, 2019
8048d9b
Update DistortableCollection.js
jywarren Jul 1, 2019
5c5753f
built dist
jywarren Jul 1, 2019
77ba8fe
further reporting of success
jywarren Jul 1, 2019
9078f56
real aerial image
jywarren Jul 1, 2019
2a5c3d6
default scale to 100
jywarren Jul 1, 2019
21f5dd4
added image_file_name to JSON
jywarren Jul 1, 2019
23e1c50
filename splice fix
jywarren Jul 1, 2019
b00eb84
filename fix
jywarren Jul 1, 2019
cc93f93
status.json update fix
jywarren Jul 1, 2019
497a474
fix for status_Url
jywarren Jul 1, 2019
5fba85f
width and height in JSON
jywarren Jul 1, 2019
a73f637
Merge branch 'multiExport' of https://github.com/sashadev-sky/Leaflet…
sashadev-sky Jul 1, 2019
acdb03a
update jshint
sashadev-sky Jul 1, 2019
eff2eb2
add new line to new file
sashadev-sky Jul 1, 2019
07a7264
re-ordered coordinates
jywarren Jul 2, 2019
2d7ad24
lon instead of lng in JSON
jywarren Jul 2, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ module.exports = function(grunt) {
noarg: true,
regexp: true,
undef: true,
unused: "strict",
trailing: true,
smarttabs: true,
globals: {
Expand Down Expand Up @@ -134,10 +133,12 @@ module.exports = function(grunt) {
"src/edit/RotateScaleHandle.js",
"src/edit/RotateHandle.js",
"src/edit/ScaleHandle.js",
"src/edit/DistortableImage.EditToolbar.js",
"src/edit/tools/EditAction.js",
"src/edit/tools/DistortableImage.PopupBar.js",
"src/edit/tools/DistortableImage.ControlBar.js",
"src/edit/DistortableImage.Edit.js",
"src/edit/tools/DistortableImage.Keymapper.js",
"src/edit/BoxSelectHandle.js"
"src/edit/DistortableImage.Keymapper.js",
"src/edit/BoxSelector.js"
],
dest: "dist/leaflet.distortableimage.js"
}
Expand Down
229 changes: 182 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ Advantages include:

[Download as zip](https://github.com/publiclab/Leaflet.DistortableImage/releases) or clone the repo to get a local copy.

This plugin has basic functionality, and is in production as part of MapKnitter, but there are [plenty of outstanding issues to resolve](https://github.com/publiclab/Leaflet.DistortableImage/issues). Please consider helping out!

The recommended Google satellite base layer can be integrated using this Leaflet plugin: https://gitlab.com/IvanSanchez/Leaflet.GridLayer.GoogleMutant

Here's a screenshot:

![screenshot](example.png)

## Setup
## Setup - Single Image Interface

1. From the root directory, run `npm install` or `sudo npm install`

Expand Down Expand Up @@ -72,6 +70,9 @@ L.DomEvent.on(img._image, 'load', img.editing.enable, img.editing);
```

Options available to pass during `L.DistortableImageOverlay` initialization:

- [actions](#Actions)

- [corners](#corners)

- [selected](#selected)
Expand All @@ -84,7 +85,30 @@ Options available to pass during `L.DistortableImageOverlay` initialization:

- [suppressToolbar](#Suppress-Toolbar)

## Corners

### Actions

- `actions` (*optional*, default: [ToggleTransparency, ToggleOutline, ToggleLock, ToggleRotateScale, ToggleOrder, EnableEXIF, Restore, Export, Delete], value: *array*)

If you would like to overrwrite the default toolbar actions available for an individual image's `L.Popup` toolbar, pass an array with the actions you want. Reference the available values [here](#Single-Image-Interface).

For example, to overrwrite the toolbar to only include the `ToggleTransparency` and `Delete` actions:

``` JS
img = L.distortableImageOverlay(
'example.png', {
// 'corners' is the only required option for this class
corners: [
L.latLng(51.52,-0.14),
L.latLng(51.52,-0.10),
L.latLng(51.50,-0.14),
L.latLng(51.50,-0.10)
],
actions: [ToggleTransparency, Delete]
}).addTo(map);
```

### Corners

The corners are stored as `L.latLng` objects
on the image, and can be accessed using our `getCorners()` method after the image is instantiated and added to the map.
Expand All @@ -108,19 +132,20 @@ JSON.stringify(img.getCorners())
=> "[{"lat":51.50685099607552,"lng":-0.06058305501937867},{"lat":51.50685099607552,"lng":-0.02058595418930054},{"lat":51.486652692081925,"lng":-0.06058305501937867},{"lat":51.486652692081925,"lng":-0.02058595418930054}]"

// note there is an added level of precision after dragging the image for debugging purposes

```
We further added a `getCorner(idx)` method used the same way as its plural counterpart but with an index passed to it.

## Selected
### Selected

`selected` (*optional*, default: false, value: *boolean*)

By default, your image will initially appear on the screen as "unselected", meaning its toolbar and editing handles will not be visible. Interacting with the image, such as by clicking it, will make these components visible.

Some developers prefer that an image initially appears as "selected" instead of "unselected". In this case, we provide an option to pass `selected: true`.

## Mode
Note: when working with the multi image interface, the collection group will ensure only the last overlay you pass `selected` to will appear initially selected.

### Mode

`mode` (*optional*, default: "distort", value: *string*)

Expand All @@ -132,15 +157,23 @@ Values available to pass to `mode` are:

- #### distort (_default_)

- Distortion via individually draggable corners.

- #### rotate

- Rotation only.

- #### scale

- Resize only.

- #### rotateScale:

- Free transform. Combines the `rotate` and `scale` modes into one.

- #### lock:

- mode which prevents any image actions (including those triggered from the toolbar, user gestures, and hotkeys) until the toolbar action [ToggleLock](#ToggleLock-(<kbd>l</kbd>)) is explicitly triggered (or its hotkey <kbd>l</kbd>)
- Prevents any image actions (including those triggered from the toolbar, user gestures, and hotkeys) until the toolbar action [ToggleLock](#ToggleLock-(<kbd>l</kbd>)) is explicitly triggered (or its hotkey <kbd>l</kbd>).

In the below example, the image will be initialiazed with "rotateScale" handles:

Expand All @@ -157,28 +190,26 @@ In the below example, the image will be initialiazed with "rotateScale" handles:
}).addTo(map);

L.DomEvent.on(img._image, 'load', img.editing.enable, img.editing);

```

## Keymapper
### Keymapper

`keymapper` (*optional*, default: true, value: *boolean*)

By default, an image loads with a keymapper legend showing the available key bindings for different editing / interaction options. To suppress the keymapper, pass `keymapper: false` as an additional option to the image.

## Full-resolution download
### Full-resolution download

We've added a GPU-accelerated means to generate a full resolution version of the distorted image; it requires two additional dependencies to enable; see how we've included them in the demo:

```
```HTML
<script src="../node_modules/webgl-distort/dist/webgl-distort.js"></script>
<script src="../node_modules/glfx/glfx.js"></script>
```

When instantiating a Distortable Image, pass in a `fullResolutionSrc` option set to the url of the higher resolution image. This image will be used in full-res exporting.

```js

```JS
// create basic map setup from above

// create an image - note the optional
Expand All @@ -195,85 +226,190 @@ img = L.distortableImageOverlay(
}).addTo(map);

L.DomEvent.on(img._image, 'load', img.editing.enable, img.editing);

```

## Suppress Toolbar
### Suppress Toolbar

`suppressToolbar` (*optional*, default: false, value: *boolean*)

To initialize an image without its toolbar, pass it `suppressToolbar: true`.

Typically, editing actions are triggered through our toolbar interface or our predefined keybindings. If disabling the toolbar, the developer will need to implement their own toolbar UI or just use the keybindings.
Typically, editing actions are triggered through our toolbar interface or our predefined keybindings. If disabling the toolbar, the developer will need to implement their own toolbar UI or just use the keybindings. (WIP API for doing this)

This option will override other options related to the toolbar, such as [`selected: true`](#Selected)

## Multiple Images
## Setup - Multiple Image Interface

To test the multi-image interface, open `select.html`. Currently it supports multiple image selection and translations; image distortions still use the single-image interface.
1. From the root directory, run `npm install` or `sudo npm install`

- Multiple images can be selected using <kbd>cmd</kbd> + `click` to toggle individual image selection.
- Click on the map or hit the <kbd>esc</kbd> key to quickly deselect all images.
2. Open `examples/select.html` in a browser (todo -- add gh pages demo)

Our `DistortableCollection` class allows working with multiple images simultaneously. Say we instantiated 3 images, saved them to the variables `img`, `img2`, and `img3`, and enabled editing on all of them. To access the UI and functionalities available in the multiple image interface, pass them to the collection class:
Our `DistortableCollection` class allows working with multiple images simultaneously. This interface builds on the single image interface.

```js
// OPTION 1: Pass in images immediately
L.distortableCollection([img, img2, img3]).addTo(map);
The setup is relatively similar - here is an example with two images:

```JS
// 1. Instantiate map
// 2. Instantiate images but this time *dont* add them directly to the map
img = L.distortableImageOverlay(
'example.png', {
keymapper: false,
corners: [
L.latLng(51.52, -0.14),
L.latLng(51.52,-0.10),
L.latLng(51.50, -0.14),
L.latLng(51.50,-0.10)
],
});

// OPTION 2: Instantiate an empty collection and pass in images later
var imageFeatureGroup = L.distortableCollection().addTo(map);
img2 = L.distortableImageOverlay(
'example.png', {
keymapper: false,
corners: [
L.latLng(51.51, -0.20),
L.latLng(51.51,-0.16),
L.latLng(51.49, -0.21),
L.latLng(51.49,-0.17)
],
});

imageFeatureGroup.addLayer(img);
imageFeatureGroup.addLayer(img2);
imageFeatureGroup.addLayer(img3);
// 3. Instantiate an empty `DistortableCollection` group
imgGroup = L.distortableCollection().addTo(map);

// 4. Add the images to the group
imgGroup.addLayer(img);
imgGroup.addLayer(img2);
```

<blockquote><strong>Note</strong>: notice how we didn't <code>enable</code> the image editing above as we had done for the single image interface. This is because our <code>DistortableCollection</code> class uses event listeners internally (<code>layeradd</code>) to enable editing on every image as it's added. This event is only triggered if we add the layers to the group dynamically. I.e. you must add the group to the map initially empty.</blockquote>

Options available to pass during `L.DistortableCollection` initialization:

- [actions](#✤-Actions)

### ✤ Actions

- `actions` (*optional*, default: [Exports, Deletes], value: *array*)

Overrwrite the default toolbar actions for an image collection's `L.Control` toolbar. Reference the available values [here](#Multiple-Image-Interface).

For example, to overrwrite the toolbar to only include the `Deletes` action:

```JS
imgGroup = L.distortableCollection({
actions: [Deletes]
}).addTo(map);
```

To add / remove a tool from the toolbar at runtime, we have also added the methods `addTool(action)` and `removeTool(action)`.

### UI and functionalities
Currently it supports multiple image selection and translations, and WIP we are working on porting all editing tools to work for it, such as transparency, etc. Image distortions still use the single-image interface.

- Multi-selection works with <kbd>cmd</kbd> + `click` to toggle an individual image's inclusion in this interface.
- Or <kbd>shift</kbd> + `drag` to use our `BoxSelector` handler to select multiple at once.
- A single toolbar instance (using `L.control`) renders the set of tools available to use on collections of images.
- In order to return to the single-image interface, where each `L.popup` toolbar only applies actions on the image it's attached to, you must toggle *all* images out of multi-select or...
- ...Click on the map or hit the <kbd>esc</kbd> key to quickly deselect all images.

<hr>

## Toolbar Actions (& Keybindings)

<hr>

### Single Image Interface:

<hr>

## Default Toolbar Actions (& Keybindings)
Defaults:

- **ToggleLock (<kbd>l</kbd>)**

#### ToggleLock (<kbd>l</kbd>)
- Toggles between [lock mode](#lock) and [distort mode](#distort-(_default_)).

- Toggles between [lock mode](#lock) and [distort mode](#distort-(_default_))
- **ToggleRotateScale (<kbd>r</kbd>, <kbd>d</kbd>)**

#### ToggleRotateScale (<kbd>r</kbd>)
- Toggles between [rotateScale](#rotateScale) and [distort mode](#distort-(_default_)).


#### ToggleOrder (<kbd>j</kbd>, <kbd>k</kbd>)
- **ToggleOrder (<kbd>j</kbd>, <kbd>k</kbd>)**

- For multiple images, switches overlapping images back and forth into view by employing [`bringToFront()`](https://leafletjs.com/reference-1.4.0.html#popup-bringtofront) and [`bringToBack()`](https://leafletjs.com/reference-1.4.0.html#popup-bringtoback) from the Leaflet API.
- If you have multiple images, use this to switch an individual image's overlap back and forth into view. Employs [`bringToFront()`](https://leafletjs.com/reference-1.5.0.html\#imageoverlay-bringtofront) and [`bringToBack()`](https://leafletjs.com/reference-1.5.0.html#imageoverlay-bringtoback) from the Leaflet API.

#### ToggleOutline (<kbd>o</kbd>)
- **ToggleOutline (<kbd>o</kbd>)**

#### ToggleTransparency (<kbd>t</kbd>)
- **ToggleTransparency (<kbd>t</kbd>)**

#### EnableEXIF (WIP)
- **EnableEXIF (WIP)**

#### Restore
- **Restore**

- Restores the image to its original proportions and scale, but keeps its current rotation angle and location intact.
- Restores the image to its original proportions and scale, but keeps its current rotation angle and location on the map intact.

#### Export
- **Export**

#### Delete (<kbd>delete</kbd>, <kbd>backscpace</kbd>)
- **Delete (<kbd>delete</kbd>, <kbd>backscpace</kbd>)**

- Permanently deletes the image from the map.
- Permanently deletes the image from the map.

## Addons
Addons:

- **ToggleRotate** (<kbd>caps lock</kbd>):

- Toggles between [rotate mode](#rotate) and [distort mode](#distort-(_default_)).
- Replaced as a default toolbar action by `ToggleRotateScale`, but still accessible via its hotkey, `mode`, and (WIP) custom toolbar actions API.


- **ToggleScale** (<kbd>s</kbd>):

- Toggles between [scale mode](#scale) and [distort mode](#distort-(_default_)).
- Replaced as a default toolbar action by `ToggleRotateScale`, but still accessible via its hotkey, `mode`, and (WIP) custom toolbar actions API.

<hr>

### Multiple Image Interface:

<hr>

Defaults:

- **Exports**

- **Deletes (<kbd>delete</kbd>, <kbd>backscpace</kbd>)**

- Permanently deletes groups of selected images from the map.

## Quick API Reference

<hr>

`L.DistortableImageOverlay`

<hr>

- [`getCorners()`](#corners) and [`getCorner(idx)`](#corners)

- `getCenter()` - Calculates the centroid of the image
- `getCenter()` - Calculates the centroid of the image.

<hr>

`L.DistortableCollection`

<hr>

- [`removeTool(action)`](#actions) - Removes the passed tool from the control toolbar in runtime.

- Ex: `imgGroup.removeTool(Deletes)`

- [`addTool(action)`](#actions) - Adds the passed tool to the control toolbar in runtime. Returns false if the tool is not available or is already present.

- `hasTool(action)` - Checks if the tool is already present in the currently rendered control toolbar.

## Contributing

This plugin has basic functionality, and is in production as part of MapKnitter, but there are [plenty of outstanding issues to resolve](https://github.com/publiclab/Leaflet.DistortableImage/issues). Please consider helping out!

1) This project uses `grunt` to do a lot of things, including concatenate source files from `/src/` to `/DistortableImageOverlay.js`:

```Bash
Expand All @@ -284,7 +420,6 @@ $ npm install -g grunt-cli
$ grunt
```


2) To build all files from `/src/` into the `/dist/` folder, run:

```Bash
Expand Down
Loading