<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MinJie</title>
    <description>The latest articles on DEV Community by MinJie (@minjieliu).</description>
    <link>https://dev.to/minjieliu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F49819%2F383556d2-d1db-4035-958c-8f80ee2b400d.jpeg</url>
      <title>DEV Community: MinJie</title>
      <link>https://dev.to/minjieliu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/minjieliu"/>
    <language>en</language>
    <item>
      <title>2022 Powerful Work: An Ultra-Delicate Picture Preview Component</title>
      <dc:creator>MinJie</dc:creator>
      <pubDate>Sat, 05 Mar 2022 08:17:20 +0000</pubDate>
      <link>https://dev.to/minjieliu/2022-powerful-work-an-ultra-delicate-picture-preview-component-2ia3</link>
      <guid>https://dev.to/minjieliu/2022-powerful-work-an-ultra-delicate-picture-preview-component-2ia3</guid>
      <description>&lt;p&gt;When I first came into the front-end industry, I had an idea, and that was to write a super cool image preview gallery.&lt;/p&gt;

&lt;p&gt;The component has been released an incomplete version a few years ago, and after intermittent maintenance, it always feels that something is wrong. There is no rest this year, and all the development is carried out on it. Now it is finally realized! First look at the effect:&lt;/p&gt;

&lt;p&gt;Thumbnail perfect gradient:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nQNWfEqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vo4ir2s2629heyex3gfb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nQNWfEqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vo4ir2s2629heyex3gfb.gif" alt="Image description" width="448" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Zoom in at a specified location:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S6LaNMeo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://s2.loli.net/2022/03/02/gtem46cBH2lwRsr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S6LaNMeo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://s2.loli.net/2022/03/02/gtem46cBH2lwRsr.gif" alt="2.gif" width="454" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slow down scrolling:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eEHuI7n9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://s2.loli.net/2022/03/02/zskQUAY8ZIlipKn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eEHuI7n9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://s2.loli.net/2022/03/02/zskQUAY8ZIlipKn.gif" alt="3.gif" width="454" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  what is &lt;code&gt;react-photo-view&lt;/code&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;react-photo-view&lt;/code&gt; has an unparalleled preview interaction experience: starting from the opening of the image, the animation, details and interaction of each frame have been carefully designed and repeatedly debugged, which is comparable to the effect of native image preview.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm i react-photo-view
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PhotoProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PhotoView&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-photo-view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-photo-view/dist/react-photo-view.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotoProvider&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotoView&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/1.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/1-thumbnail.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/PhotoView&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/PhotoProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why develop it separately?
&lt;/h3&gt;

&lt;p&gt;Of course, the obsession to realize it is also an aspect, but the fundamental reason is that in the powerful ecosystem of &lt;code&gt;React&lt;/code&gt;, there is simply no easy-to-use image preview solution. At that time, I followed the principle of use, and I found a circle of &lt;code&gt;React&lt;/code&gt;-based zoom preview component libraries on the Internet. The result surprised me a bit. The number of image zoom preview libraries is obviously not comparable to the carousel component library. What is even more suffocating is that most of these meager component libraries are secondary encapsulation based on the &lt;code&gt;PhotoSwipe&lt;/code&gt; open source library. In addition, the preview component library that can be used in actual production... It seems that there is no (or maybe I can't find it), this situation is not only reflected in the &lt;code&gt;React&lt;/code&gt; library, other frameworks &lt;code&gt;Vue&lt;/code&gt; and even native related Libraries are like that.&lt;/p&gt;

&lt;p&gt;Of course, &lt;code&gt;PhotoSwipe&lt;/code&gt; is not unusable, but the native operation &lt;code&gt;DOM&lt;/code&gt; is out of place in &lt;code&gt;React&lt;/code&gt;, and its volume is also above &lt;code&gt;gzip 12KB&lt;/code&gt;, which is a bit bloated, so I have this bold idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  How good is it?
&lt;/h3&gt;

&lt;p&gt;It has very perfect details and features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support touch gestures, drag and pan physical effect sliding, two-finger specified position to zoom in and out&lt;/li&gt;
&lt;li&gt;All aspects of animation connection, open and close the rebound touch edge, let the natural interaction effect&lt;/li&gt;
&lt;li&gt;The image is adaptive, with a suitable initial rendering size, and adapts according to the adjustment&lt;/li&gt;
&lt;li&gt;Support for custom previews like &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; or any &lt;code&gt;HTML&lt;/code&gt; element&lt;/li&gt;
&lt;li&gt;Keyboard navigation, perfect for desktop&lt;/li&gt;
&lt;li&gt;Support custom node expansion, easy to achieve full-screen preview, rotation control, picture introduction and more functions&lt;/li&gt;
&lt;li&gt;Based on &lt;code&gt;typescript&lt;/code&gt;, &lt;code&gt;7KB Gzipped&lt;/code&gt;, supports server-side rendering&lt;/li&gt;
&lt;li&gt;Simple and easy to use &lt;code&gt;API&lt;/code&gt;, zero cost to get started&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also exports &lt;code&gt;JS&lt;/code&gt; that supports &lt;code&gt;ES2017&lt;/code&gt; and above, and can achieve &lt;code&gt;6KB Gzipped&lt;/code&gt;. It is not easy to add a lot of experience details to such a volume. More functions can be achieved through very easy custom rendering, which is perfectly in line with the &lt;code&gt;React&lt;/code&gt; concept, thus avoiding built-in functions that are not rigidly needed. .&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison of popular libraries
&lt;/h3&gt;

&lt;p&gt;The following table summarizes the functions required for most scenarios, showing a comparison of &lt;code&gt;react-photo-view&lt;/code&gt; , &lt;code&gt;PhotoSwipe&lt;/code&gt; and &lt;code&gt;rc-image&lt;/code&gt; (ant-design):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;react-photo-view&lt;/th&gt;
&lt;th&gt;PhotoSwipe&lt;/th&gt;
&lt;th&gt;rc-image&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MINIFIED&lt;/td&gt;
&lt;td&gt;19KB&lt;/td&gt;
&lt;td&gt;47KB&lt;/td&gt;
&lt;td&gt;40KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MINIFIED + GZIPPED&lt;/td&gt;
&lt;td&gt;7.3KB&lt;/td&gt;
&lt;td&gt;12KB&lt;/td&gt;
&lt;td&gt;14KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Basic preview&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Toggle preview&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thumbnail perfect gradient&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thumbnail crop animation&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support（need to be specified manually）&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adaptive Image Size&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support（need to be specified manually）&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fallback&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mouse wheel zoom&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;td&gt;（missing location）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spring physical roll&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Animation parameter adjustment&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy-to-use API&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keyboard navigation&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom element&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Risk of XSS&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;controlled&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loop preview&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rotation&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom toolbar&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full screen&lt;/td&gt;
&lt;td&gt;custom extension&lt;/td&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Not support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Friendly documentation
&lt;/h3&gt;

&lt;p&gt;What's more important than documentation, and for this, I also prepared a super beautiful document&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react-photo-view.vercel.app/"&gt;https://react-photo-view.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P1m8Pnoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bw23npcrlun1age23yea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P1m8Pnoz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bw23npcrlun1age23yea.png" alt="Image description" width="880" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Realization process
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Image scrolls with your finger
&lt;/h4&gt;

&lt;p&gt;Record the current trigger position state in &lt;code&gt;onTouchStart&lt;/code&gt;, let it follow the finger movement in &lt;code&gt;onTouchMove&lt;/code&gt;, and &lt;code&gt;onTouchEnd&lt;/code&gt; can be easily implemented.&lt;/p&gt;

&lt;p&gt;The touch position feedback makes the picture switching need to slowly ponder the details: moving after &lt;code&gt;onTouchStart&lt;/code&gt;, if the picture follows the finger movement immediately, it will bring many misoperations, such as the logic of sliding up and down when you want to switch the picture . At this time, a &lt;code&gt;20px&lt;/code&gt; movement buffer is needed to predict the direction of the finger movement.&lt;/p&gt;

&lt;h4&gt;
  
  
  Specify image location to zoom in
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;transform: scale(value)&lt;/code&gt; to scale the image, but the center of the image is zoomed in, and the result of the scaling may not be what you want. Originally intended to use &lt;code&gt;transform-origin&lt;/code&gt; to achieve, the idea is good, although the first time can be zoomed in at the specified position. If the reduced position is not the original position, there will be chaotic beating. Obviously, this method will not work.&lt;/p&gt;

&lt;p&gt;Later, I couldn't sleep after thinking about it, and found inspiration in my sleep: to facilitate calculation and understanding, we set the center point of the picture as &lt;code&gt;0&lt;/code&gt;, and zooming in and out of any specified position means changing the position of the center of the picture. For example, the image width is &lt;code&gt;200&lt;/code&gt;, the center point position is &lt;code&gt;100&lt;/code&gt;, and it is doubled based on the leftmost position. Now the image width is &lt;code&gt;400&lt;/code&gt;, then the position of the center point should be &lt;code&gt;200&lt;/code&gt;. Then the summary formula is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;centerClientX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Coordinate offset conversion&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastPositionX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;centerClientX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;lastX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// zoom offset&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offsetScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextScale&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// final offset position&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;clientX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastPositionX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;offsetScale&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;centerClientX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mode of computing can take on various positional responses, such as pinch-to-zoom, pinch-to-scroll+zoom, edge computing, and more.&lt;/p&gt;

&lt;h4&gt;
  
  
  Distance between fingers
&lt;/h4&gt;

&lt;p&gt;This requires the right triangle Pythagorean theorem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;nextClientX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextClientY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Simulate scrolling
&lt;/h4&gt;

&lt;p&gt;The previous version was implemented using &lt;code&gt;transition&lt;/code&gt;. The initial speed was calculated by the time difference between the start and end of the finger sliding, and it was estimated that the &lt;code&gt;transition&lt;/code&gt; was used to simulate a distance to make the eyes look like a scrolling effect 😂. But this way the experience is always much worse. Later, combined with the high school physics formula, the rolling effect is simulated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rGKkqo9w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s2.loli.net/2022/03/02/qd27QLtS4lDWgXm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rGKkqo9w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s2.loli.net/2022/03/02/qd27QLtS4lDWgXm.png" alt="5.png" width="139" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Accelerated movement:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N0X3u9o7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s2.loli.net/2022/03/02/h9JQwWCpte3ryzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N0X3u9o7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s2.loli.net/2022/03/02/h9JQwWCpte3ryzx.png" alt="6.png" width="282" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Air resistance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BgSI4gDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s2.loli.net/2022/03/02/S6Mt3VxYksDodEc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BgSI4gDI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://s2.loli.net/2022/03/02/S6Mt3VxYksDodEc.png" alt="7.png" width="197" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CρS&lt;/code&gt; are all constants, so just make them a quantity. As for how to get this amount... I tried it out 😂 This is only proportional to the square of &lt;code&gt;v&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In addition, because it is opposite to the direction of motion, take the direction of &lt;code&gt;v&lt;/code&gt; that is &lt;code&gt;Math.sign(-v)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;scrollMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;initialSpeed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spatial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resistance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;frameId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calcMove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;lastTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;lastTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;lastTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialSpeed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;resistance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// move to s&lt;/span&gt;
    &lt;span class="nx"&gt;lastTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cancelAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frameId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;frameId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calcMove&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;cancelAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frameId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;frameId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calcMove&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Thumbnail crop
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;PhotoSwipe&lt;/code&gt; supports thumbnail cropping, but you need to manually specify the image width and height and &lt;code&gt;data-cropped&lt;/code&gt;, which is quite troublesome. &lt;code&gt;react-photo-view&lt;/code&gt; gets the current cropping parameters by reading the thumbnail &lt;code&gt;getComputedStyle(element).objectFit&lt;/code&gt;. Realize automatic cropping effect.&lt;/p&gt;

&lt;h4&gt;
  
  
  Compatibility Handling
&lt;/h4&gt;

&lt;p&gt;Since each image is a composite layer, this consumes quite a bit of memory. &lt;code&gt;IOS&lt;/code&gt; has a considerable memory limit, if the image is always using &lt;code&gt;scale&lt;/code&gt; when zoomed in, it will appear very blurry on &lt;code&gt;Safari&lt;/code&gt;. Now by changing the width and height of the image to the specified value every time after the movement is completed, and then resetting the &lt;code&gt;scale&lt;/code&gt; to 1, this method should achieve the desired effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other
&lt;/h3&gt;

&lt;p&gt;The author of &lt;code&gt;PhotoSwipe&lt;/code&gt; is a Ukrainian living in Kyiv who fled Kyiv and is now safe with his family in western Ukraine, and hopes he will bounce back after the war.&lt;/p&gt;

&lt;h3&gt;
  
  
  epilogue
&lt;/h3&gt;

&lt;p&gt;I spent a lot of time on the details of &lt;code&gt;react-photo-view&lt;/code&gt;, if you like it, you can help me by clicking &lt;code&gt;Star&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MinJieLiu/react-photo-view"&gt;https://github.com/MinJieLiu/react-photo-view&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

</description>
      <category>react</category>
      <category>photoswipe</category>
      <category>gallery</category>
      <category>carousel</category>
    </item>
  </channel>
</rss>
