在 clojurescript/试剂中跟踪鼠标并在屏幕上渲染点?
Tracking mouse and render dot at the screen in clojurescript / reagent?
我对 clojurescript 很陌生,也许这是一个微不足道的问题,但我还没有设法找到答案。
我期待实现一个 clojurescript 来跟踪鼠标并在鼠标位置渲染一个点,如下所示:
https://jsbin.com/gejuz/1/edit?html,output
Js代码:
function() {
"use strict";
document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
var dot, eventDoc, doc, body, pageX, pageY;
event = event || window.event; // IE-ism
// If pageX/Y aren't available and clientX/Y
// are, calculate pageX/Y - logic taken from jQuery
// Calculate pageX/Y if missing and clientX/Y available
if (event.pageX == null && event.clientX != null) {
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}
// Add a dot to follow the cursor
dot = document.createElement('div');
dot.className = "dot";
dot.style.left = event.pageX + "px";
dot.style.top = event.pageY + "px";
document.body.appendChild(dot);
}
到目前为止,我确实设法获得了鼠标坐标(感谢这个问题Tracking mouse in clojurescript / reagent / reagi?)。但我无法在网页中呈现该点。
Clojurescript 代码:
(def mouse-coordinates (reagent/atom {:x 100 :y 100}))
(defn dot [x y]
[:div {:style {:left (str x "px")
:top (str y "px")
:width "2px"
:height "2px"
:background-clor "black"
:position "absolute"}}])
(def do-dot (reagent/reactify-component dot))
(defn mouse-move []
[:body
{:onMouseMove (fn [event]
(swap! mouse-coordinates assoc :x (.-clientX event))
(swap! mouse-coordinates assoc :y (.-clientY event))
(reagent/create-element do-dot
#js{:x (int (:x @mouse-coordinates))
:y (int (:y @mouse-coordinates))})
)}
[:p "x: " (int (:x @mouse-coordinates))]
[:p "y: " (int (:y @mouse-coordinates))]
])
(reagent/render-component [mouse-move]
(. js/document (getElementById "app")))
感谢任何帮助。提前谢谢你。
您可以将 dot
组件作为呈现代码的一部分,而不是在 onMouseMove
事件中创建元素。它将获取 reagent/atom
的更改,就像两个 p
元素所做的那样:
[:p "x: " (int (:x @mouse-coordinates))]
[:p "y: " (int (:y @mouse-coordinates))]
[dot (int (:x @mouse-coordinates)) (int (:y @mouse-coordinates))]
还有一个错字::background-clor
-> :background-color
。这两个变化应该足以使圆点出现。
还有其他一些有助于简化代码的东西:
如果您传入数字,style
属性将默认为像素
所以dot
组件可以这样写:
(defn dot [x y]
[:div {:style {:left x
:top y
:width 2
:height 2
:background-color "black"
:position "absolute"}}])
reset!
对比 swap!
- 因为
mouse-coordinates
有一个非常特殊的用途,所以在 onMouseMove
事件中使用 reset!
而不是 swap!
会更整洁一些:
(reset! mouse-coordinates {:x (.-clientX event) :y (.-clientY event)})
将组件道具作为地图传入
(defn dot [{:keys [x y]}]
...)
[dot @mouse-coordinates]
最终代码看起来像这样:
(def mouse-coordinates (reagent/atom {:x 100 :y 100}))
(defn dot [{:keys [x y]}]
[:div {:style {:left x
:top y
:width 2
:height 2
:background-color "black"
:position "absolute"}}])
(defn mouse-move []
[:body
{:onMouseMove (fn [event]
(reset! mouse-coordinates {:x (.-clientX event) :y (.-clientY event)}))}
[:p "x: " (:x @mouse-coordinates)]
[:p "y: " (:y @mouse-coordinates)]
[dot @mouse-coordinates]])
更新:当我第一次回答这个问题时,我没有意识到每个点都应该是持久的。这是关于如何实现这一点的更新代码(带有注释):
使用坐标集合
(def mouse-coordinates (r/atom []))
(defn dot [{:keys [x y]}]
[:div {:style {:left x
:top y
:width 2
:height 2
:background-color "black"
:position "absolute"}}])
(defn mouse-move []
[:div
{:onMouseMove (fn [event]
(let [x (.-clientX event)
y (.-clientY event)
;; If there's already a dot in an identical location, don't add it. This saves unnecessary work and
;; means we can use [x y] as our unique key for our collection.
coords-already-exist? (not (empty? (filter #(and (= (:x %) x) (= (:y %) y)) @mouse-coordinates)))]
(when-not coords-already-exist?
;; conj the new coordinate to the collection.
(swap! mouse-coordinates #(conj % {:x (.-clientX event) :y (.-clientY event)})))))}
[:p "x: " (:x @mouse-coordinates)]
[:p "y: " (:y @mouse-coordinates)]
;; Loop through the coordinates.
(for [{:keys [x y]} @mouse-coordinates]
[dot
;; Important: we give each dot a unique key.
{:key [x y]
:x x
:y y}])])
如评论中所述,呈现集合的重要之处在于为每个项目赋予唯一键。这意味着随着新坐标的创建,React 知道添加一个新的子节点而不是重新渲染每个 dot
。更多信息可以在 React 文档中找到:https://reactjs.org/docs/lists-and-keys.html#keys
我对 clojurescript 很陌生,也许这是一个微不足道的问题,但我还没有设法找到答案。
我期待实现一个 clojurescript 来跟踪鼠标并在鼠标位置渲染一个点,如下所示:
https://jsbin.com/gejuz/1/edit?html,output
Js代码:
function() {
"use strict";
document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
var dot, eventDoc, doc, body, pageX, pageY;
event = event || window.event; // IE-ism
// If pageX/Y aren't available and clientX/Y
// are, calculate pageX/Y - logic taken from jQuery
// Calculate pageX/Y if missing and clientX/Y available
if (event.pageX == null && event.clientX != null) {
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}
// Add a dot to follow the cursor
dot = document.createElement('div');
dot.className = "dot";
dot.style.left = event.pageX + "px";
dot.style.top = event.pageY + "px";
document.body.appendChild(dot);
}
到目前为止,我确实设法获得了鼠标坐标(感谢这个问题Tracking mouse in clojurescript / reagent / reagi?)。但我无法在网页中呈现该点。
Clojurescript 代码:
(def mouse-coordinates (reagent/atom {:x 100 :y 100}))
(defn dot [x y]
[:div {:style {:left (str x "px")
:top (str y "px")
:width "2px"
:height "2px"
:background-clor "black"
:position "absolute"}}])
(def do-dot (reagent/reactify-component dot))
(defn mouse-move []
[:body
{:onMouseMove (fn [event]
(swap! mouse-coordinates assoc :x (.-clientX event))
(swap! mouse-coordinates assoc :y (.-clientY event))
(reagent/create-element do-dot
#js{:x (int (:x @mouse-coordinates))
:y (int (:y @mouse-coordinates))})
)}
[:p "x: " (int (:x @mouse-coordinates))]
[:p "y: " (int (:y @mouse-coordinates))]
])
(reagent/render-component [mouse-move]
(. js/document (getElementById "app")))
感谢任何帮助。提前谢谢你。
您可以将 dot
组件作为呈现代码的一部分,而不是在 onMouseMove
事件中创建元素。它将获取 reagent/atom
的更改,就像两个 p
元素所做的那样:
[:p "x: " (int (:x @mouse-coordinates))]
[:p "y: " (int (:y @mouse-coordinates))]
[dot (int (:x @mouse-coordinates)) (int (:y @mouse-coordinates))]
还有一个错字::background-clor
-> :background-color
。这两个变化应该足以使圆点出现。
还有其他一些有助于简化代码的东西:
如果您传入数字,style
属性将默认为像素
所以dot
组件可以这样写:
(defn dot [x y]
[:div {:style {:left x
:top y
:width 2
:height 2
:background-color "black"
:position "absolute"}}])
reset!
对比 swap!
- 因为
mouse-coordinates
有一个非常特殊的用途,所以在onMouseMove
事件中使用reset!
而不是swap!
会更整洁一些:
(reset! mouse-coordinates {:x (.-clientX event) :y (.-clientY event)})
将组件道具作为地图传入
(defn dot [{:keys [x y]}]
...)
[dot @mouse-coordinates]
最终代码看起来像这样:
(def mouse-coordinates (reagent/atom {:x 100 :y 100}))
(defn dot [{:keys [x y]}]
[:div {:style {:left x
:top y
:width 2
:height 2
:background-color "black"
:position "absolute"}}])
(defn mouse-move []
[:body
{:onMouseMove (fn [event]
(reset! mouse-coordinates {:x (.-clientX event) :y (.-clientY event)}))}
[:p "x: " (:x @mouse-coordinates)]
[:p "y: " (:y @mouse-coordinates)]
[dot @mouse-coordinates]])
更新:当我第一次回答这个问题时,我没有意识到每个点都应该是持久的。这是关于如何实现这一点的更新代码(带有注释):
使用坐标集合
(def mouse-coordinates (r/atom []))
(defn dot [{:keys [x y]}]
[:div {:style {:left x
:top y
:width 2
:height 2
:background-color "black"
:position "absolute"}}])
(defn mouse-move []
[:div
{:onMouseMove (fn [event]
(let [x (.-clientX event)
y (.-clientY event)
;; If there's already a dot in an identical location, don't add it. This saves unnecessary work and
;; means we can use [x y] as our unique key for our collection.
coords-already-exist? (not (empty? (filter #(and (= (:x %) x) (= (:y %) y)) @mouse-coordinates)))]
(when-not coords-already-exist?
;; conj the new coordinate to the collection.
(swap! mouse-coordinates #(conj % {:x (.-clientX event) :y (.-clientY event)})))))}
[:p "x: " (:x @mouse-coordinates)]
[:p "y: " (:y @mouse-coordinates)]
;; Loop through the coordinates.
(for [{:keys [x y]} @mouse-coordinates]
[dot
;; Important: we give each dot a unique key.
{:key [x y]
:x x
:y y}])])
如评论中所述,呈现集合的重要之处在于为每个项目赋予唯一键。这意味着随着新坐标的创建,React 知道添加一个新的子节点而不是重新渲染每个 dot
。更多信息可以在 React 文档中找到:https://reactjs.org/docs/lists-and-keys.html#keys