Browse Source

improve(pdf): support zoom in/out viewer

charlie 4 years ago
parent
commit
2d04b0a614

+ 14 - 1
src/main/frontend/components/svg.cljs

@@ -591,4 +591,17 @@
      :stroke-linecap "round"}]])
 
 (def home
-  [:svg.h-6.w-6 {:fill "none" :viewbox "0 0 24 24" :stroke "currentColor"} [:path {:stroke-linecap "round" :stroke-linejoin "round" :stroke-width "2" :d "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"}]])
+  [:svg.h-6.w-6 {:fill "none" :viewbox "0 0 24 24" :stroke "currentColor"}
+   [:path {:stroke-linecap "round" :stroke-linejoin "round" :stroke-width "2" :d "M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"}]])
+
+(defn zoom-in
+  ([] (zoom-in 16))
+  ([size]
+   [:svg {:xmlns "http://www.w3.org/2000/svg" :width size :height size :fill "none" :viewBox "0 0 24 24" :stroke "currentColor"}
+    [:path {:stroke-linecap "round" :stroke-linejoin "round" :stroke-width "2" :d "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7"}]]))
+
+(defn zoom-out
+  ([] (zoom-out 16))
+  ([size]
+   [:svg {:fill "none" :width size :height size :viewBox "0 0 24 24" :stroke "currentColor"}
+    [:path {:stroke-linecap "round" :stroke-linejoin "round" :stroke-width "2" :d "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7"}]]))

+ 31 - 14
src/main/frontend/extensions/pdf/highlights.cljs

@@ -8,6 +8,7 @@
             [frontend.util :as front-utils]
             [frontend.state :as state]
             [frontend.config :as config]
+            [frontend.components.svg :as svg]
             [medley.core :as medley]
             [frontend.fs :as fs]
             [clojure.string :as string]))
@@ -163,13 +164,19 @@
         show-ctx-tip! (fn [^js viewer hl point]
                         (let [vw-pos (pdf-utils/scaled-to-vw-pos viewer (:position hl))]
                           (set-tip-state! {:highlight hl :vw-pos vw-pos :point point})))
+
         add-hl! (fn [hl] (when (:id hl)
                            ;; fix js object
-                           (let [highlights (map #(if (map? %) % (bean/->clj %)) highlights)]
+                           (let [highlights (pdf-utils/fix-nested-js highlights)]
                              (set-highlights! (conj highlights hl)))))
+
         upd-hl! (fn [hl]
-                  (when-let [pp (medley/find-first #(= (:id (second %)) (:id hl)) (medley/indexed highlights))]
-                    (set-highlights! (assoc-in highlights [(first pp)] hl))))
+                  (let [highlights (pdf-utils/fix-nested-js highlights)]
+                    (when-let [[target-idx] (medley/find-first
+                                              #(= (:id (second %)) (:id hl))
+                                              (medley/indexed highlights))]
+                      (set-highlights! (assoc-in highlights [target-idx] hl)))))
+
         del-hl! (fn [hl] (when-let [id (:id hl)] (set-highlights! (into [] (remove #(= id (:id %)) highlights)))))]
 
     ;; consume dirtied
@@ -306,6 +313,24 @@
            (:text (:content hl))])
         ])]))
 
+(rum/defc pdf-toolbar
+  [^js viewer]
+  [:div.extensions__pdf-toolbar
+   [:div.r.flex
+
+    ;; zoom
+    [:a.button
+     {:on-click (partial pdf-utils/zoom-out-viewer viewer)}
+     (svg/zoom-out)]
+
+    [:a.button
+     {:on-click (partial pdf-utils/zoom-in-viewer viewer)}
+     (svg/zoom-in)]
+
+    [:a.button
+     {:on-click #(state/set-state! :pdf/current nil)}
+     "close"]]])
+
 (rum/defc pdf-viewer
   [url initial-hls ^js pdf-document ops]
 
@@ -389,15 +414,8 @@
             initial-hls (:loaded-pages ano-state)
             ops) "pdf-highlights")
 
-        (rum/with-key
-          (pdf-resizer viewer) "pdf-resizer")])]))
-
-(rum/defc pdf-toolbar
-  []
-  [:div.extensions__pdf-toolbar
-   [:div.r
-    [:a.button {:on-click #(state/set-state! :pdf/current nil)} "close"]
-    ]])
+        (rum/with-key (pdf-toolbar viewer) "pdf-toolbar")
+        (rum/with-key (pdf-resizer viewer) "pdf-resizer")])]))
 
 (rum/defc pdf-loader
   [{:keys [url hls-file]}]
@@ -486,8 +504,7 @@
          [:div.flex.justify-center.items-center.h-screen.text-gray-500.text-md
           "Downloading PDF file " url]
 
-         [(rum/with-key (pdf-toolbar) "pdf-toolbar")
-          (rum/with-key (pdf-viewer
+         [(rum/with-key (pdf-viewer
                           url initial-hls
                           (:pdf-document state)
                           {:set-dirty-hls! set-dirty-hls!}) "pdf-viewer")]))]))

+ 9 - 0
src/main/frontend/extensions/pdf/pdf.css

@@ -64,6 +64,15 @@
     align-items: center;
     justify-content: flex-end;
     padding-right: 20px;
+
+    > .r {
+      a.button {
+        user-select: none;
+        display: flex;
+        align-items: center;
+        margin-left: 8px;
+      }
+    }
   }
 
   &-viewer {

+ 29 - 0
src/main/frontend/extensions/pdf/utils.cljs

@@ -5,6 +5,10 @@
             ["/frontend/extensions/pdf/utils" :as js-utils]
             [frontend.loader :refer [load]]))
 
+(defonce MAX-SCALE 5.0)
+(defonce MIN-SCALE 0.25)
+(defonce DELTA_SCALE 1.1)
+
 (defn get-bounding-rect
   [rects]
   (bean/->clj (js-utils/getBoundingRect (bean/->js rects))))
@@ -55,6 +59,26 @@
   (when-let [js-hl (bean/->js hl)]
     (js-utils/scrollToHighlight viewer js-hl)))
 
+(defn zoom-in-viewer
+  [^js viewer]
+  (let [cur-scale (.-currentScale viewer)]
+    (when (< cur-scale MAX-SCALE)
+      (let [new-scale (.toFixed (* cur-scale DELTA_SCALE) 2)
+            new-scale (/ (js/Math.ceil (* new-scale 10)) 10)
+            new-scale (min MAX-SCALE new-scale)]
+
+        (set! (.-currentScale viewer) new-scale)))))
+
+(defn zoom-out-viewer
+  [^js viewer]
+  (let [cur-scale (.-currentScale viewer)]
+    (when (> cur-scale MIN-SCALE)
+      (let [new-scale (.toFixed (/ cur-scale DELTA_SCALE) 2)
+            new-scale (/ (js/Math.floor (* new-scale 10)) 10)
+            new-scale (max MIN-SCALE new-scale)]
+
+        (set! (.-currentScale viewer) new-scale)))))
+
 (defn clear-all-selection
   []
   (.removeAllRanges (js/window.getSelection)))
@@ -63,6 +87,11 @@
   (front-utils/debounce
     200 (fn [^js viewer] (set! (. viewer -currentScaleValue) "auto"))))
 
+(defn fix-nested-js
+  [its]
+  (when (sequential? its)
+    (mapv #(if (map? %) % (bean/->clj %)) its)))
+
 (defn gen-id []
   (str (.toString (js/Date.now) 36)
        (.. (js/Math.random) (toString 36) (substr 2 4))))