android - 使用 React Native 进行精确绘图
问题描述
我需要一些帮助来弄清楚如何在 React Native 中精确绘图。我之前在(原生)iOS 上做过这种事情,但还没有在 Android 上做过,所以我可能会错过一个 Android 的东西,但我最好只使用 React Native 方法来解决这个问题,而不是求助于实现自定义视图。
我正在尝试绘制乐谱的五线谱,例如:
我正在使用FlatList
水平模式下的 React Native 来执行此操作。我在内容单元格内绘制垂直线作为分隔符和水平线。在这一点上,这就是我所关心的,还不是数字等。
我尝试了两种使用 React Native 绘制它的方法:
- PNG;我提供普通、@2x 和@3x 版本并将它们呈现在
ImageBackground
标签中。这适用于 iOS,但在 Android 上,线条并不能完美对齐,因此垂直线和水平线连接不好,存在间隙,并且垂直组件的大小不一样,因此它们是太短。这是因为 @2x 和 @3x 对于 iOS 来说是完美的像素,但仍需要为 Android 进行缩放? - SVG (
react-native-svg
); 这给出了类似的问题。同样在 iOS 上的结果相当不错,但在 Android 上的像素排列不正确。为了说明这一点,请参见以下三个屏幕截图。
Android低分辨率设备(emu)上的SVG:很奇怪不同部分的高度有很大不同:
Android高分辨率设备(emu)上的SVG:水平线不连续,垂直线超出上下人员:
我不明白为什么这会变成它在 Android 上的方式。我不确定我是否使用正确的方法来实现这一点。我应该使用什么方法?任何帮助深表感谢!
下面是相关的源代码。它在 ClojureScript 中,但即使您不熟悉它,您也应该能够识别 SVG 的构建方式。我小心地使用半像素值作为线坐标和方形结尾,以便理论上所有内容都应该准确地排列在像素上。
(defn bar-lines [width]
(take 5 (map (fn [y] ^{:key (str y)}
[:> Line {:x1 0.5 :y1 y :x2 (+ 0.5 (dec width)) :y2 y
:stroke-width 1 :stroke "black"
:stroke-linecap "square"}])
(iterate (partial + 8) 0.5))))
(defn cell [details]
(let [item (details "item")
num (item "measureNumber")]
[:> ViewOverflow {:style {:width 68 :height 65}}
[:> Svg {:height 34 :width 68 :view-box "0 0 68 33"
:style {:position "absolute" :bottom 0}}
(bar-lines 68)]]))
(defn single-line-separator []
[:> ViewOverflow {:style {:width 1 :height 65}}
[:> Svg {:height 34 :width 1 :view-box "0 0 1 33"
:style {:position "absolute" :bottom 0}}
[:> Line {:x1 0.5 :y1 0.5 :x2 0.5 :y2 32.5 :stroke-linecap "square" :stroke-width 1 :stroke "black"}]]])
(defn double-line-separator []
[:> ViewOverflow {:style {:width 3 :height 65}}
[:> Svg {:height 34 :width 3 :view-box "0 0 3 33"
:style {:position "absolute" :bottom 0}}
[:> Line {:x1 0.5 :y1 0.5 :x2 0.5 :y2 32.5 :stroke-linecap "square" :stroke-width 1 :stroke "black"}]
[:> Line {:x1 2.5 :y1 0.5 :x2 2.5 :y2 32.5 :stroke-linecap "square" :stroke-width 1 :stroke "black"}]
(bar-lines 3)]])
(defn separator [props]
(if (show-double-bar? (.-measureNumber (.-leadingItem props)))
(double-line-separator)
(single-line-separator)))
(defn header []
[:> rn/View {:style {:width 15 :height 65}}
[:> Svg {:height 34 :width 15 :view-box "0 0 15 33"
:style {:position "absolute" :bottom 0}}
(bar-lines 15)
[:> Line {:x1 14.5 :y1 0.5 :x2 14.5 :y2 32.5 :stroke-linecap "square" :stroke-width 1 :stroke "black"}]]])
(defn footer []
[:> rn/View {:style {:width 11 :height 65}}
[:> Svg {:height 34 :width 11 :view-box "0 0 11 33"
:style {:position "absolute" :bottom 0}}
[:> Line {:x1 0.5 :y1 0.5 :x2 0.5 :y2 32.5 :stroke-linecap "square" :stroke-width 1 :stroke "black"}]
[:> Line {:x1 4.5 :y1 1.5 :x2 4.5 :y2 31.5 :stroke-linecap "square" :stroke-width 3 :stroke "black"}]
(bar-lines 3)]])
(defn Staff [styles]
[:> rn/View styles
[:> rn/FlatList
{:data (clj->js (mapv (fn [n] {:key (str n) :measureNumber n}) (range 1 4)))
:horizontal true
:Cell-renderer-component ViewOverflow
:List-header-component #(r/as-element [header])
:List-footer-component #(r/as-element [footer])
:Item-separator-component #(r/as-element [separator %])
:render-item (fn [details] (r/as-element [cell (js->clj details)]))}]])
解决方案
推荐阅读
- android - 分页无法正常工作 Android。它一次显示所有项目
- html - Flex 物品无法正确包裹和收缩
- python - Django 无法分配“'Pizza'”:“Order.Food_Name”必须是“Foods”实例
- android - 如何在 EditText DrawableRight 上执行点击监听?
- r - R如何将MultiLineString GeoJson文件转换为具有长列和纬度列的数据框?
- laravel - Laravel Passport 在 AuthServiceProvider 中抛出错误
- javascript - javascript 的对象通过引用传递的例外是什么?
- testing - 在 Idris 中测试证明是否合理
- python - nunique 不包括 pandas 中的一些值
- c# - 我们如何使用脚本在 prefeb(prefeb 包含两种原始类型形状)中淡入淡出 unity3