croppable 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -1
- data/app/assets/javascripts/croppable.js +11 -26
- data/lib/croppable/crop.rb +18 -23
- data/lib/croppable/model.rb +2 -6
- data/lib/croppable/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d7748fdc65361664f5e6b39b0c8bb68a64453f7bb47a43a3957cd3984e60115
|
4
|
+
data.tar.gz: 2f2c3b3cce9896172e1f2117ae25e3e4d537230c2fc38a1dc742cbaf04d37157
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c43837b3fa737eaa8006a8e57f8fb78467bf5a54ffeb0877f501066a892a66eb7ca3ff4a8b19398215ced4ca15c4fda45e71ae59317f54a7b1c74e492d34757
|
7
|
+
data.tar.gz: b5edca4cffaef90aed0ba2c8233c17b737a1a06353b3ceac2fbc1a1ee13052764d0080126662b52a387e5cdc2ac56294d734edf1900115ac0815375aef74f7c0
|
data/README.md
CHANGED
@@ -54,9 +54,13 @@ brew install vips
|
|
54
54
|
## Usage
|
55
55
|
Add has_croppable into your model
|
56
56
|
```ruby
|
57
|
-
has_croppable :logo, width: 300, height: 300
|
57
|
+
has_croppable :logo, width: 300, height: 300, scale: 2
|
58
58
|
```
|
59
59
|
|
60
|
+
`width` and `height` are in pixels and required.
|
61
|
+
|
62
|
+
`scale: 2` will generate an image twice as big. Useful for retina display monitors. It defaults to 1.
|
63
|
+
|
60
64
|
Add croppable_field to your form
|
61
65
|
```ruby
|
62
66
|
form.croppable_field :logo
|
@@ -1,20 +1,11 @@
|
|
1
1
|
import Cropper from 'cropperjs';
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
return Turbolinks.supported;
|
6
|
-
} catch(_) {
|
7
|
-
return false;
|
8
|
-
}
|
9
|
-
}
|
10
|
-
|
11
|
-
if(isTurbolinksEnabled()) {
|
12
|
-
document.addEventListener('turbo:load', start)
|
13
|
-
} else {
|
14
|
-
document.addEventListener('DOMContentLoaded', start)
|
15
|
-
}
|
3
|
+
document.addEventListener('turbo:load', start);
|
4
|
+
document.addEventListener('DOMContentLoaded', start);
|
16
5
|
|
17
6
|
function start() {
|
7
|
+
document.removeEventListener('DOMContentLoaded', start)
|
8
|
+
|
18
9
|
const dropAreas = document.getElementsByClassName('croppable-droparea');
|
19
10
|
|
20
11
|
Array.from(dropAreas).forEach((dropArea) => {
|
@@ -50,7 +41,7 @@ function start() {
|
|
50
41
|
input.files = event.dataTransfer.files;
|
51
42
|
|
52
43
|
const image = document.createElement('img');
|
53
|
-
image.src
|
44
|
+
image.src = URL.createObjectURL(file);
|
54
45
|
|
55
46
|
updateImageDisplay(image, wrapper, true, input)
|
56
47
|
}
|
@@ -85,7 +76,9 @@ function updateImageDisplay(image, wrapper, isNewImage, input) {
|
|
85
76
|
|
86
77
|
dropArea.classList.add("inactive");
|
87
78
|
container.classList.add("active");
|
88
|
-
|
79
|
+
|
80
|
+
deleteInput.checked = false;
|
81
|
+
controls.style.display = "flex";
|
89
82
|
|
90
83
|
cleanContainer()
|
91
84
|
|
@@ -94,20 +87,13 @@ function updateImageDisplay(image, wrapper, isNewImage, input) {
|
|
94
87
|
const cropperImage = cropper.getCropperImage();
|
95
88
|
const cropperCanvas = cropper.getCropperCanvas();
|
96
89
|
|
97
|
-
|
90
|
+
cropperCanvas.style.backgroundColor = bgColorBtn.value;
|
98
91
|
|
99
92
|
var saveTransform = false;
|
100
93
|
|
101
94
|
cropperImage.$ready(() => {
|
102
95
|
if (xInput.value != "" && !isNewImage) {
|
103
|
-
var waitForTranform =
|
104
|
-
|
105
|
-
// Turbolinks hack to actually apply initial transformation
|
106
|
-
if(isTurbolinksEnabled) {
|
107
|
-
waitForTranform = 10;
|
108
|
-
} else {
|
109
|
-
waitForTranform = 0;
|
110
|
-
}
|
96
|
+
var waitForTranform = 10; // needed due turbolinks 🤦
|
111
97
|
|
112
98
|
setTimeout(() => {
|
113
99
|
cropperImage.$setTransform(+scaleInput.value, 0, 0, +scaleInput.value, +xInput.value, +yInput.value);
|
@@ -116,6 +102,7 @@ function updateImageDisplay(image, wrapper, isNewImage, input) {
|
|
116
102
|
}, waitForTranform)
|
117
103
|
} else {
|
118
104
|
const matrix = cropperImage.$getTransform();
|
105
|
+
|
119
106
|
xInput.value = matrix[4];
|
120
107
|
yInput.value = matrix[5];
|
121
108
|
scaleInput.value = matrix[0];
|
@@ -133,8 +120,6 @@ function updateImageDisplay(image, wrapper, isNewImage, input) {
|
|
133
120
|
}
|
134
121
|
});
|
135
122
|
|
136
|
-
cropperCanvas.style.backgroundColor = bgColorBtn.value;
|
137
|
-
|
138
123
|
bgColorBtn.addEventListener("change", (event) => {
|
139
124
|
event.preventDefault();
|
140
125
|
cropperCanvas.style.backgroundColor = event.target.value;
|
data/lib/croppable/crop.rb
CHANGED
@@ -2,45 +2,40 @@ require 'open-uri'
|
|
2
2
|
require 'vips'
|
3
3
|
|
4
4
|
module Croppable
|
5
|
-
|
6
5
|
class Crop
|
7
6
|
def initialize(model, attr_name)
|
8
7
|
@model = model
|
9
8
|
@attr_name = attr_name
|
10
9
|
@data = model.send("#{attr_name}_croppable_data")
|
11
10
|
@setup = model.send("#{attr_name}_croppable_setup")
|
12
|
-
original = model.send("#{attr_name}_original")
|
13
|
-
@url = Rails.application.routes.url_helpers.rails_blob_url(original, host: Rails.application.config.asset_host)
|
14
11
|
end
|
15
12
|
|
16
13
|
def perform()
|
17
|
-
|
18
|
-
|
14
|
+
@model.send("#{@attr_name}_original").open do |file|
|
15
|
+
vips_img = Vips::Image.new_from_file(file.path)
|
16
|
+
|
17
|
+
height = vips_img.height
|
18
|
+
width = vips_img.width
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
x = ((width - (width * @data.scale)) / 2 + @data.x) * @setup[:scale]
|
21
|
+
y = ((height - (height * @data.scale)) / 2 + @data.y) * @setup[:scale]
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
background = @data.background_color.remove("#").scan(/\w{2}/).map {|color| color.to_i(16) }
|
24
|
+
background_embed = background.dup
|
25
|
+
background_embed << 255 if vips_img.bands == 4
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
background_embed << 255 if vips_img.bands == 4
|
27
|
+
new_width = @setup[:width] * @setup[:scale]
|
28
|
+
new_height = @setup[:height] * @setup[:scale]
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
x * @setup[:resolution],
|
33
|
-
y * @setup[:resolution],
|
34
|
-
@setup[:width] * @setup[:resolution],
|
35
|
-
@setup[:height] * @setup[:resolution],
|
36
|
-
background: background_embed
|
37
|
-
)
|
30
|
+
vips_img = vips_img.resize(@data.scale * @setup[:scale])
|
31
|
+
vips_img = vips_img.embed(x, y, new_width, new_height, background: background_embed)
|
38
32
|
|
39
|
-
|
33
|
+
path = Tempfile.new('cropped').path + ".jpg"
|
40
34
|
|
41
|
-
|
35
|
+
vips_img.write_to_file(path, background: background, Q: 100)
|
42
36
|
|
43
|
-
|
37
|
+
@model.send("#{ @attr_name }_cropped").attach(io: File.open(path), filename: "cropped")
|
38
|
+
end
|
44
39
|
end
|
45
40
|
end
|
46
41
|
end
|
data/lib/croppable/model.rb
CHANGED
@@ -2,12 +2,8 @@ module Croppable
|
|
2
2
|
module Model
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
|
-
# High-resolution displays, which are a large part of the market, need twice
|
6
|
-
# the pixels to look professional.
|
7
|
-
DEFAULT_RESOLUTION = 2
|
8
|
-
|
9
5
|
class_methods do
|
10
|
-
def has_croppable(name, width:, height:,
|
6
|
+
def has_croppable(name, width:, height:, scale: 1)
|
11
7
|
has_one_attached :"#{ name }_cropped"
|
12
8
|
has_one_attached :"#{ name }_original"
|
13
9
|
|
@@ -20,7 +16,7 @@ module Croppable
|
|
20
16
|
|
21
17
|
generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
22
18
|
def #{ name }_croppable_setup
|
23
|
-
{width: #{ width }, height: #{ height },
|
19
|
+
{width: #{ width }, height: #{ height }, scale: #{ scale }}
|
24
20
|
end
|
25
21
|
|
26
22
|
def to_crop_croppable
|
data/lib/croppable/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: croppable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Barragán Naranjo
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
version: '1.2'
|
41
41
|
description:
|
42
42
|
email:
|
43
|
-
-
|
43
|
+
- stvnbarragan@gmail.com
|
44
44
|
executables: []
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
@@ -74,11 +74,11 @@ files:
|
|
74
74
|
- lib/croppable/version.rb
|
75
75
|
- lib/generators/croppable/install/install_generator.rb
|
76
76
|
- lib/tasks/croppable_tasks.rake
|
77
|
-
homepage: https://
|
77
|
+
homepage: https://rubygems.org/gems/croppable
|
78
78
|
licenses:
|
79
79
|
- MIT
|
80
80
|
metadata:
|
81
|
-
homepage_uri: https://
|
81
|
+
homepage_uri: https://rubygems.org/gems/croppable
|
82
82
|
source_code_uri: https://github.com/stevenbarragan/croppable
|
83
83
|
post_install_message:
|
84
84
|
rdoc_options: []
|