mirror of
https://github.com/penpot/penpot.git
synced 2025-01-09 16:30:37 -05:00
✨ Adds blending mode and opacities to shapes
This commit is contained in:
parent
d39694af59
commit
31fa4a8c8b
4 changed files with 167 additions and 10 deletions
|
@ -394,13 +394,15 @@
|
|||
|
||||
(defn name
|
||||
"Improved version of name that won't fail if the input is not a keyword"
|
||||
[maybe-keyword]
|
||||
(cond
|
||||
(keyword? maybe-keyword)
|
||||
(core/name maybe-keyword)
|
||||
([maybe-keyword] (name maybe-keyword nil))
|
||||
([maybe-keyword default-value]
|
||||
(cond
|
||||
(keyword? maybe-keyword)
|
||||
(core/name maybe-keyword)
|
||||
|
||||
(nil? maybe-keyword) nil
|
||||
(nil? maybe-keyword) default-value
|
||||
|
||||
:else
|
||||
(str maybe-keyword)))
|
||||
:else
|
||||
(or default-value
|
||||
(str maybe-keyword)))))
|
||||
|
||||
|
|
|
@ -910,14 +910,16 @@
|
|||
.element-set-actions {
|
||||
display: flex;
|
||||
visibility: hidden;
|
||||
|
||||
}
|
||||
|
||||
.row-flex-removable:hover .element-set-actions,
|
||||
.element-set-options-group:hover .element-set-actions {
|
||||
visibility: visible;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.layer-actions {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.typography-entry {
|
||||
margin: 0.5rem 0.3rem;
|
||||
|
|
|
@ -120,6 +120,17 @@
|
|||
(obj/merge! attrs (clj->js stroke-attrs)))
|
||||
attrs)))
|
||||
|
||||
(defn add-layer-props [attrs shape]
|
||||
(let [layer-attrs
|
||||
(cond-> {}
|
||||
(:opacity shape)
|
||||
(assoc :opacity (:opacity shape))
|
||||
|
||||
(and (:blend-mode shape) (not= (:blend-mode shape) :normal))
|
||||
(assoc :mixBlendMode (:blend-mode shape)))]
|
||||
|
||||
(obj/merge! attrs (clj->js layer-attrs))))
|
||||
|
||||
(defn extract-svg-attrs
|
||||
[render-id svg-defs svg-attrs]
|
||||
(let [replace-id (fn [id]
|
||||
|
@ -147,7 +158,8 @@
|
|||
styles (-> (obj/new)
|
||||
(obj/merge! svg-styles)
|
||||
(add-fill shape render-id)
|
||||
(add-stroke shape render-id))]
|
||||
(add-stroke shape render-id)
|
||||
(add-layer-props shape))]
|
||||
|
||||
(-> (obj/new)
|
||||
(obj/merge! svg-attrs)
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020-2021 UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.layer
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.math :as mth]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(def layer-attrs [:opacity :blend-mode :blocked :hidden])
|
||||
|
||||
(defn opacity->string [opacity]
|
||||
(if (= opacity :multiple)
|
||||
""
|
||||
(str (-> opacity
|
||||
(d/coalesce 1)
|
||||
(* 100)
|
||||
(mth/round)))))
|
||||
|
||||
(defn select-all [event]
|
||||
(dom/select-text! (dom/get-target event)))
|
||||
|
||||
(mf/defc layer-menu [{:keys [ids type values]}]
|
||||
(let [change!
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [prop value]
|
||||
(st/emit! (dwc/update-shapes ids #(assoc % prop value)))))
|
||||
|
||||
handle-change-blend-mode
|
||||
(mf/use-callback
|
||||
(mf/deps change!)
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-target-val event) (keyword))]
|
||||
(change! :blend-mode value))))
|
||||
|
||||
handle-opacity-change
|
||||
(mf/use-callback
|
||||
(mf/deps change!)
|
||||
(fn [value]
|
||||
(let [value (-> value (/ 100))]
|
||||
(change! :opacity value))))
|
||||
|
||||
handle-set-hidden
|
||||
(mf/use-callback
|
||||
(mf/deps change!)
|
||||
(fn [event]
|
||||
(change! :hidden true)))
|
||||
|
||||
handle-set-visible
|
||||
(mf/use-callback
|
||||
(mf/deps change!)
|
||||
(fn [event]
|
||||
(change! :hidden false)))
|
||||
|
||||
handle-set-blocked
|
||||
(mf/use-callback
|
||||
(mf/deps change!)
|
||||
(fn [event]
|
||||
(change! :blocked true)))
|
||||
|
||||
handle-set-unblocked
|
||||
(mf/use-callback
|
||||
(mf/deps change!)
|
||||
(fn [event]
|
||||
(change! :blocked false)))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span
|
||||
(case type
|
||||
:multiple (tr "workspace.options.layer-options.title.multiple")
|
||||
:group (tr "workspace.options.layer-options.title.group")
|
||||
(tr "workspace.options.layer-options.title"))]]
|
||||
|
||||
[:div.element-set-content
|
||||
[:div.row-flex
|
||||
[:select.input-select {:on-change handle-change-blend-mode
|
||||
:value (d/name (:blend-mode values) "normal")}
|
||||
|
||||
(when (= :multiple (:blend-mode values))
|
||||
[:option {:value "multiple"} "--"])
|
||||
|
||||
[:option {:value "normal"} (tr "workspace.options.layer-options.blend-mode.normal")]
|
||||
|
||||
[:option {:value "darken"} (tr "workspace.options.layer-options.blend-mode.darken")]
|
||||
[:option {:value "multiply"} (tr "workspace.options.layer-options.blend-mode.multiply")]
|
||||
[:option {:value "color-burn"} (tr "workspace.options.layer-options.blend-mode.color-burn")]
|
||||
|
||||
[:option {:value "lighten"} (tr "workspace.options.layer-options.blend-mode.lighten")]
|
||||
[:option {:value "screen"} (tr "workspace.options.layer-options.blend-mode.screen")]
|
||||
[:option {:value "color-dodge"} (tr "workspace.options.layer-options.blend-mode.color-dodge")]
|
||||
|
||||
[:option {:value "overlay"} (tr "workspace.options.layer-options.blend-mode.overlay")]
|
||||
[:option {:value "soft-light"} (tr "workspace.options.layer-options.blend-mode.soft-light")]
|
||||
[:option {:value "hard-light"} (tr "workspace.options.layer-options.blend-mode.hard-light")]
|
||||
|
||||
[:option {:value "difference"} (tr "workspace.options.layer-options.blend-mode.difference")]
|
||||
[:option {:value "exclusion"} (tr "workspace.options.layer-options.blend-mode.exclusion")]
|
||||
|
||||
[:option {:value "hue"} (tr "workspace.options.layer-options.blend-mode.hue")]
|
||||
[:option {:value "saturation"} (tr "workspace.options.layer-options.blend-mode.saturation")]
|
||||
[:option {:value "color"} (tr "workspace.options.layer-options.blend-mode.color")]
|
||||
[:option {:value "luminosity"} (tr "workspace.options.layer-options.blend-mode.luminosity")]]
|
||||
|
||||
[:div.input-element
|
||||
{:class "percentail"}
|
||||
[:> numeric-input {:value (-> values :opacity opacity->string)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-click select-all
|
||||
:on-change handle-opacity-change
|
||||
:min 0
|
||||
:max 100}]]
|
||||
|
||||
|
||||
[:div.element-set-actions.layer-actions
|
||||
(cond
|
||||
(or (= :multiple (:hidden values)) (not (:hidden values)))
|
||||
[:div.element-set-actions-button {:on-click handle-set-hidden} i/eye]
|
||||
|
||||
:else
|
||||
[:div.element-set-actions-button {:on-click handle-set-visible} i/eye-closed])
|
||||
|
||||
(cond
|
||||
(or (= :multiple (:blocked values)) (not (:blocked values)))
|
||||
[:div.element-set-actions-button {:on-click handle-set-blocked} i/lock-open]
|
||||
|
||||
:else
|
||||
[:div.element-set-actions-button {:on-click handle-set-unblocked} i/lock])]]]]))
|
Loading…
Reference in a new issue