mirror of
https://github.com/penpot/penpot.git
synced 2025-03-12 07:41:43 -05:00
Merge pull request #4146 from penpot/alotor-us-6933-keep-aspect-ratio
Add keep aspect ratio flag
This commit is contained in:
commit
c4e707d5a2
13 changed files with 94 additions and 29 deletions
|
@ -22,8 +22,8 @@
|
|||
:proportion (/ width height)
|
||||
:proportion-lock true)))
|
||||
|
||||
(defn setup-proportions-svg
|
||||
[{:keys [width height] :as shape}]
|
||||
(defn setup-proportions-size
|
||||
[{{:keys [width height]} :selrect :as shape}]
|
||||
(assoc shape
|
||||
:proportion (/ width height)
|
||||
:proportion-lock true))
|
||||
|
@ -35,9 +35,11 @@
|
|||
:proportion-lock false))
|
||||
|
||||
(defn setup-proportions
|
||||
[shape]
|
||||
(case (:type shape)
|
||||
:svg-raw (setup-proportions-svg shape)
|
||||
:image (setup-proportions-image shape)
|
||||
:text shape
|
||||
(setup-proportions-const shape)))
|
||||
[{:keys [type] :as shape}]
|
||||
(let [image-fill? (every? #(some? (:fill-image %)) (:fills shape))]
|
||||
(cond
|
||||
(= type :svg-raw) (setup-proportions-size shape)
|
||||
(= type :image) (setup-proportions-image shape)
|
||||
image-fill? (setup-proportions-size shape)
|
||||
(= type :text) shape
|
||||
:else (setup-proportions-const shape))))
|
||||
|
|
|
@ -52,7 +52,8 @@
|
|||
[:width :int]
|
||||
[:height :int]
|
||||
[:mtype {:optional true} [:maybe :string]]
|
||||
[:id ::sm/uuid]])
|
||||
[:id ::sm/uuid]
|
||||
[:keep-aspect-ratio {:optional true} :boolean]])
|
||||
|
||||
(sm/define! ::gradient
|
||||
[:map {:title "Gradient"}
|
||||
|
|
|
@ -72,7 +72,8 @@
|
|||
:width width
|
||||
:height height
|
||||
:mtype mtype
|
||||
:id id}}]}]
|
||||
:id id
|
||||
:keep-aspect-ratio true}}]}]
|
||||
(rx/of (dwsh/create-and-add-shape :rect x y shape))))))
|
||||
|
||||
(defn svg-uploaded
|
||||
|
@ -358,7 +359,8 @@
|
|||
:id id
|
||||
:width width
|
||||
:height height
|
||||
:mtype mtype}}]
|
||||
:mtype mtype
|
||||
:keep-aspect-ratio true}}]
|
||||
:name name
|
||||
:frame-id (:id frame-shape)
|
||||
:parent-id (:id frame-shape)})]
|
||||
|
|
|
@ -117,9 +117,10 @@
|
|||
:style style}]
|
||||
(if (:fill-image value)
|
||||
(let [uri (cf/resolve-file-media (:fill-image value))
|
||||
keep-ar? (-> value :fill-image :keep-aspect-ratio)
|
||||
image-props #js {:id (dm/str "fill-image-" render-id "-" fill-index)
|
||||
:href (get uris uri uri)
|
||||
:preserveAspectRatio "xMidYMid slice"
|
||||
:preserveAspectRatio (if keep-ar? "xMidYMid slice" "none")
|
||||
:width width
|
||||
:height height
|
||||
:key (dm/str fill-index)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
grid-template-areas: "left-sidebar viewport right-sidebar";
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
overflow: hidden;
|
||||
|
||||
.workspace-loader {
|
||||
@include flexCenter;
|
||||
|
|
|
@ -84,7 +84,10 @@
|
|||
on-fill-image-success
|
||||
(mf/use-fn
|
||||
(fn [image]
|
||||
(st/emit! (dc/update-colorpicker-color {:image (select-keys image [:id :width :height :mtype :name])} (not @drag?)))))
|
||||
(st/emit! (dc/update-colorpicker-color
|
||||
{:image (-> (select-keys image [:id :width :height :mtype :name])
|
||||
(assoc :keep-aspect-ratio true))}
|
||||
(not @drag?)))))
|
||||
|
||||
on-fill-image-click
|
||||
(mf/use-callback #(dom/click (mf/ref-val fill-image-ref)))
|
||||
|
@ -94,6 +97,16 @@
|
|||
(fn [file]
|
||||
(st/emit! (dwm/upload-fill-image file on-fill-image-success))))
|
||||
|
||||
handle-change-keep-aspect-ratio
|
||||
(mf/use-fn
|
||||
(mf/deps current-color)
|
||||
(fn []
|
||||
(let [keep-aspect-ratio? (-> current-color :image :keep-aspect-ratio not)]
|
||||
(st/emit! (dc/update-colorpicker-color
|
||||
{:image (-> (:image current-color)
|
||||
(assoc :keep-aspect-ratio keep-aspect-ratio?))}
|
||||
true)))))
|
||||
|
||||
set-tab!
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
|
@ -248,11 +261,24 @@
|
|||
:on-select-stop handle-change-stop}])
|
||||
|
||||
(if (= selected-mode :image)
|
||||
(let [uri (cfg/resolve-file-media (:image current-color))]
|
||||
(let [uri (cfg/resolve-file-media (:image current-color))
|
||||
keep-aspect-ratio? (-> current-color :image :keep-aspect-ratio)]
|
||||
[:div {:class (stl/css :select-image)}
|
||||
[:div {:class (stl/css :content)}
|
||||
(when (:image current-color)
|
||||
[:img {:src uri}])]
|
||||
|
||||
(when (some? (:image current-color))
|
||||
[:div {:class (stl/css :checkbox-option)}
|
||||
[:label {:for "keep-aspect-ratio"
|
||||
:class (stl/css-case :global/checked keep-aspect-ratio?)}
|
||||
[:span {:class (stl/css-case :global/checked keep-aspect-ratio?)}
|
||||
(when keep-aspect-ratio? i/status-tick-refactor)]
|
||||
(tr "media.keep-aspect-ratio")
|
||||
[:input {:type "checkbox"
|
||||
:id "keep-aspect-ratio"
|
||||
:checked keep-aspect-ratio?
|
||||
:on-change handle-change-keep-aspect-ratio}]]])
|
||||
[:button
|
||||
{:class (stl/css :choose-image)
|
||||
:title (tr "media.choose-image")
|
||||
|
|
|
@ -166,3 +166,8 @@
|
|||
margin-top: $s-12;
|
||||
height: $s-32;
|
||||
}
|
||||
|
||||
.checkbox-option {
|
||||
@extend .input-checkbox;
|
||||
margin: $s-16 0 0 0;
|
||||
}
|
||||
|
|
|
@ -166,16 +166,16 @@
|
|||
:y -11
|
||||
:width (max 0 (- text-width text-pos-x))
|
||||
:height 20
|
||||
:class "workspace-frame-label"
|
||||
:class (stl/css :workspace-frame-label-wrapper)
|
||||
:style {:fill color}
|
||||
:visibility (if show-artboard-names? "visible" "hidden")
|
||||
:on-pointer-down on-pointer-down
|
||||
:on-double-click on-double-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave}
|
||||
:visibility (if show-artboard-names? "visible" "hidden")}
|
||||
[:div {:class (stl/css :workspace-frame-label)
|
||||
:style {:color color}}
|
||||
:style {:color color}
|
||||
:on-pointer-down on-pointer-down
|
||||
:on-double-click on-double-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave}
|
||||
(if show-id?
|
||||
(dm/str (dm/str (:id frame)) " - " (:name frame))
|
||||
(:name frame))]]])))
|
||||
|
|
|
@ -63,10 +63,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
.workspace-frame-label-wrapper {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.workspace-frame-label {
|
||||
font-size: $fs-12;
|
||||
color: black;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
max-width: fit-content;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
|
|
@ -347,7 +347,12 @@
|
|||
(->> (upload-media-files context file-id name (:href image-data))
|
||||
(rx/catch #(do (.error js/console "Error uploading media: " name)
|
||||
(rx/of node)))
|
||||
(rx/map #(vector (:id image-data) %)))))
|
||||
(rx/map (fn [data]
|
||||
(let [data
|
||||
(cond-> data
|
||||
(some? (:keep-aspect-ratio image-data))
|
||||
(assoc :keep-aspect-ratio (:keep-aspect-ratio image-data)))]
|
||||
[(:id image-data) data]))))))
|
||||
(rx/reduce (fn [acc [id data]] (assoc acc id data)) {})
|
||||
(rx/map
|
||||
(fn [images]
|
||||
|
@ -360,7 +365,8 @@
|
|||
(assoc-in [:attrs :penpot:media-width] (:width media))
|
||||
(assoc-in [:attrs :penpot:media-height] (:height media))
|
||||
(assoc-in [:attrs :penpot:media-mtype] (:mtype media))
|
||||
|
||||
(cond-> (some? (:keep-aspect-ratio media))
|
||||
(assoc-in [:attrs :penpot:media-keep-aspect-ratio] (:keep-aspect-ratio media)))
|
||||
(assoc-in [:attrs :penpot:fill-color] (:fill image-fill))
|
||||
(assoc-in [:attrs :penpot:fill-color-ref-file] (:fill-color-ref-file image-fill))
|
||||
(assoc-in [:attrs :penpot:fill-color-ref-id] (:fill-color-ref-id image-fill))
|
||||
|
|
|
@ -195,15 +195,22 @@
|
|||
(d/deep-mapm
|
||||
(fn [pair] (->> pair (mapv convert)))))))
|
||||
|
||||
(def search-data-node? #{:rect :image :path :circle})
|
||||
(def search-data-node? #{:rect :path :circle})
|
||||
|
||||
(defn get-svg-data
|
||||
[type node]
|
||||
|
||||
(let [node-attrs (add-attrs {} (:attrs node))]
|
||||
(cond
|
||||
(search-data-node? type)
|
||||
(let [data-tags #{:ellipse :rect :path :text :foreignObject :image}]
|
||||
(let [data-tags #{:ellipse :rect :path :text :foreignObject}]
|
||||
(->> node
|
||||
(node-seq)
|
||||
(filter #(contains? data-tags (:tag %)))
|
||||
(map #(:attrs %))
|
||||
(reduce add-attrs node-attrs)))
|
||||
|
||||
(= type :image)
|
||||
(let [data-tags #{:rect :image}]
|
||||
(->> node
|
||||
(node-seq)
|
||||
(filter #(contains? data-tags (:tag %)))
|
||||
|
@ -523,7 +530,8 @@
|
|||
(let [metadata {:id (get-meta node :media-id)
|
||||
:width (get-meta node :media-width)
|
||||
:height (get-meta node :media-height)
|
||||
:mtype (get-meta node :media-mtype)}]
|
||||
:mtype (get-meta node :media-mtype)
|
||||
:keep-aspect-ratio (get-meta node :media-keep-aspect-ratio str->bool)}]
|
||||
(cond-> props
|
||||
(= type :image)
|
||||
(assoc :metadata metadata)
|
||||
|
@ -881,7 +889,8 @@
|
|||
(let [id (get-in fill-node [:attrs :penpot:fill-image-id])
|
||||
image-node (->> node (node-seq) (find-node-by-id id))]
|
||||
{:id id
|
||||
:href (get-in image-node [:attrs :href])})))
|
||||
:href (get-in image-node [:attrs :href])
|
||||
:keep-aspect-ratio (not= (get-in image-node [:attrs :preserveAspectRatio]) "none")})))
|
||||
(filterv #(some? (:id %))))))
|
||||
|
||||
(defn has-fill-images?
|
||||
|
|
|
@ -5074,6 +5074,9 @@ msgstr "Gradient"
|
|||
msgid "media.choose-image"
|
||||
msgstr "Choose image"
|
||||
|
||||
msgid "media.keep-aspect-ratio"
|
||||
msgstr "Keep aspect ratio"
|
||||
|
||||
msgid "workspace.options.guides.title"
|
||||
msgstr "Guides"
|
||||
|
||||
|
|
|
@ -5158,6 +5158,9 @@ msgstr "Gradiente"
|
|||
msgid "media.choose-image"
|
||||
msgstr "Elegir imagen"
|
||||
|
||||
msgid "media.keep-aspect-ratio"
|
||||
msgstr "Mantener la proporción"
|
||||
|
||||
msgid "workspace.options.guides.title"
|
||||
msgstr "Guías"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue