Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用React Native中的动画将一个svg路径转换为另一个svg路径?_Javascript_Reactjs_React Native_Svg_Jsx - Fatal编程技术网

Javascript 如何使用React Native中的动画将一个svg路径转换为另一个svg路径?

Javascript 如何使用React Native中的动画将一个svg路径转换为另一个svg路径?,javascript,reactjs,react-native,svg,jsx,Javascript,Reactjs,React Native,Svg,Jsx,每当用户单击文本输入时,我想将SVG路径或形状从曲线更改为矩形。如何使用动画或从曲线过渡到矩形形状?使曲线上升,直到变成一条直线。 我可以做到这一点,但没有动画。 如下图所示: 以下是我的JSX代码: return ( <KeyboardAvoidingView style={{ flex: 1 }} behavior="padding" enabled> <View style={styles.container}> <

每当用户单击文本输入时,我想将SVG路径或形状从曲线更改为矩形。如何使用动画或从曲线过渡到矩形形状?使曲线上升,直到变成一条直线。 我可以做到这一点,但没有动画。 如下图所示:

以下是我的JSX代码:

return (
    <KeyboardAvoidingView style={{ flex: 1 }} behavior="padding" enabled>
      <View style={styles.container}>
          <Svg height={280} width={WIDTH}>
            <Path
              d= { numInputTouched? "M0 0 V200 C0 200, 400 400, 0" + WIDTH + ", 120 V0 ":"M0 0 V200 H" + WIDTH + ", V0"}
              //"M0 0 V200 H" + WIDTH + ", V0"
              //   d={"M0 0 V200 C0 200, 400 400, 0" + WIDTH + ", 120 V0"}
              fill={Colors.primary}
              stroke={Colors.primary}
            />
            <View style={styles.titleContaier}>
              <Text style={styles.title}>
                اشتراك / تسجيل الدخول{"\n"}
                <Text style={styles.subTitle}>ادخل رقم موبايلك</Text>
              </Text>
            </View>
          </Svg>

        <Text style={styles.SMSText}>ستصلك رسالة قصيرة تحتوي على رمز</Text>
        <View style={{}}>
          <View style={styles.numberInputContainer}>
            <View style={styles.numberInput}>
              <View style={{}}>
                <Text style={styles.numberTextFixed}>07</Text>
              </View>
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[1]}
                onKeyPress={textHandler(1)}
                keyboardType="number-pad"
                onChangeText={text => setText1(text)}
                onTouchStart={() => setNumInputTouched(true)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[2]}
                onKeyPress={textHandler(2)}
                onChangeText={text => setText2(text)}
                keyboardType="number-pad"
                value={text2}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[3]}
                onKeyPress={textHandler(3)}
                keyboardType="number-pad"
                onChangeText={text => setText3(text)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[4]}
                onKeyPress={textHandler(4)}
                keyboardType="number-pad"
                onChangeText={text => setText4(text)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[5]}
                onKeyPress={textHandler(5)}
                keyboardType="number-pad"
                onChangeText={text => setText5(text)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[6]}
                onKeyPress={textHandler(6)}
                keyboardType="number-pad"
                onChangeText={text => setText6(text)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[7]}
                onKeyPress={textHandler(7)}
                keyboardType="number-pad"
                onChangeText={text => setText7(text)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[8]}
                onKeyPress={textHandler(8)}
                keyboardType="number-pad"
                onChangeText={text => setText8(text)}
              />
              <TextInput
                style={styles.numberText}
                placeholder="X"
                maxLength={1}
                ref={textInput[9]}
                onKeyPress={textHandler(9)}
                keyboardType="number-pad"
                onChangeText={text => setText9(text)}
              />
            </View>
          </View>
          <View>
            <TouchableOpacity
              style={{ alignItems: "flex-end", width: "85%", marginTop: 50 }}
            >
              <View style={styles.buttonContainer}>
                <Ionicons
                  name="ios-arrow-round-forward"
                  size={45}
                  color="white"
                  style={styles.icon}
                />
              </View>
            </TouchableOpacity>
          </View>
        </View>
      </View>
    </KeyboardAvoidingView>
  );
};
返回(
ا
ادخل رقم موبايلك
ستصلك رسالة قصيرة تحتوي على رمز
07
setText1(文本)}
onTouchStart={()=>setNumInputTouched(true)}
/>
setText2(文本)}
keyboardType=“数字键盘”
值={text2}
/>
setText3(文本)}
/>
setText4(文本)}
/>
setText5(文本)}
/>
setText6(文本)}
/>
setText7(文本)}
/>
setText8(文本)}
/>
setText9(文本)}
/>
);
};

好的,我有一种方法可以在vanilla JavaScript-Demo中实现:

我以前从未使用过React-Native,所以我无法给出确切的代码,但我认为这个概念是最重要的

我的HTML如下所示:

<button id="forwards">Forwards</button>
<button id="backwards">Backwards</button>
<Svg height="280" width="400">
  <Path id="target" d="M0 0 V200 C0 200, 400 400, 0400, 120 V0 " fill="#85ffda" stroke="#85ffda"/>
  <g transform="translate(0,00)">
  <path d="M0 0 V200 Q 395 370 400 120 V0 Z" stroke-width="1" stroke="black" fill="transparent"/>
  <path d="M0 0 V200 Q 300 300 400 150 V0 Z" stroke="black" fill="transparent"/>
  <path d="M0 0 V200 Q 250 250 400 175 V0 Z" stroke="black" fill="transparent"/>
  <path d="M0 0 V200 Q 250 200 400 200 V0 Z" stroke="black" fill="transparent"/>
  </g>
</svg>
// d= { numInputTouched? "M0 0 V200 C0 200, 400 400, 0" + WIDTH + ", 120 V0 ":"M0 0 V200 H" + WIDTH + ", V0"}
//         //"M0 0 V200 H" + WIDTH + ", V0"
//         //   d={"M0 0 V200 C0 200, 400 400, 0" + WIDTH + ", 120 V0"}

const WIDTH = 400;
const svg = document.querySelector("svg");
svg.setAttribute('width', WIDTH);

const before = ['M', [0,0], 'V', [200], 'Q', [395, 370], ' ', [WIDTH, 120], 'V', [0], 'Z'];
const after = ['M', [0,0], 'V', [200], 'Q', [180, 200], ' ', [WIDTH, 200], 'V', [0], 'Z'];
const diff = ['M', [0,0], 'V', [0], 'Q', [-145, -170], ' ', [0, 80], 'V', [0], 'Z'];

console.log(before.join(' '))

// const target = document.getElementById("target");
// target.setAttribute('d', "M0 0 V200 H" + WIDTH + ", V0");    
// target.setAttribute('d', "M0 0 V200 C0 200, 400 400, 0" + WIDTH + ", 120 V0 ");

target.setAttribute('d', before.join(' '));

var current = ['M', [0,0], 'V', [200], 'Q', [395, 370], ' ', [400, 120], 'V', [0], 'Z'];

function transition(i) {
  current[1][0] = before[1][0] + Math.round((i/100)*diff[1][0],0);
  current[1][1] = before[1][1] + Math.round((i/100)*diff[1][1],0);
  current[3][0] = before[3][0] + Math.round((i/100)*diff[3][0],0);
  current[5][0] = before[5][0] + Math.round((i/100)*diff[5][0],0);
  current[5][1] = before[5][1] + Math.round((i/100)*diff[5][1],0);
  current[7][0] = before[7][0] + Math.round((i/100)*diff[7][0],0);
  current[7][1] = before[7][1] + Math.round((i/100)*diff[7][1],0);
  target.setAttribute('d', current.join(' '));  
}
console.log(current.join(' '));

var progress = 0;
var timeInterval; //to be started at a later time

function myTimerForward() {
  console.log(progress);
  if (progress == 100) {    
    clearInterval(timeInterval);
  } else {
    progress += 1;
    transition(progress);
  }
}

function myTimerBackward() {
  console.log(progress);
  if (progress == 0) {    
    clearInterval(timeInterval);
  } else {
    progress -= 1;
    transition(progress);
  }
}

document.querySelector("#forwards").addEventListener('click', function() {
  timeInterval = setInterval(myTimerForward, 10);
});

document.querySelector("#backwards").addEventListener('click', function() {
  timeInterval = setInterval(myTimerBackward, 10);
});
总之,我稍微更改了svg路径形状,使其更简单(但形状相同)-我使用了更简单的贝塞尔曲线,二次曲线-

另一种类型的贝塞尔曲线,称为Q的二次曲线,是 实际上是一条比三次曲线更简单的曲线

这样我就可以用数组简单地描述曲线:

const before = ['M', [0,0], 'V', [200], 'Q', [395, 370], ' ', [WIDTH, 120], 'V', [0], 'Z'];
随着时间的推移,会过渡到:

const after = ['M', [0,0], 'V', [200], 'Q', [180, 200], ' ', [WIDTH, 200], 'V', [0], 'Z'];
两者的区别在于:

const diff = ['M', [0,0], 'V', [0], 'Q', [-145, -170], ' ', [0, 80], 'V', [0], 'Z'];
这意味着我可以把这个差异的一小部分加在前面,我们会慢慢达到最终的结果

剩下的只是设置一个setInterval,以便每10毫秒启动一次函数,慢慢地将形状转换为最终结果。我不确定您是否会在ReactNative中使用相同的setInterval等

这会导致在单击“前进”按钮时在曲线和平面之间移动,以及在单击“后退”按钮时在平面和曲线之间移动。在您的示例中,您会在某种onFocus事件上触发相关函数,等等

例如:

(注意:黑线只是路径,只有一些指导方针可以显示此转换是如何发生的)

使用SMIL更新

还有使用SMIL(同步多媒体集成语言)的选项-我不能100%确定这在React native中是否有效,但我认为是这样

演示:

然后我们可以简化我们的代码。我们只需要首先在HTML中添加一个animate元素标记,它描述了动画:

<Svg height="400" width="400"> 
  <Path id="target" d="M0 0 V200 Q 395 370 400 120 V0 Z" fill="#85ffda" stroke="#85ffda">
    <animate
       attributeName="d"
       from="M0 0 V200 Q 395 370 400 120 V0 Z"
       to="M0 0 V200 Q 180 200 400 200 V0 Z"
       dur="0.5s" repeatCount="1" begin="indefinite" fill="freeze" />  
  </path>
  ...
</svg>

我们只需要捕获
from=“…”
to=“…”
属性,这样我们就可以在反向运行时翻转它们,以及捕获路径的当前
d=“…”
属性。这是必要的,如果我们在另一个完成之前开始转换,以确保我们不会得到一个跳跃的动画重新启动其位置等。然后,最后只需将这些功能附加到输入/按钮的单击/聚焦事件,我们就完成了

嘿,Ali,我在中制作了一个等价的演示,仅用于薄荷色的svg路径。明天我将尝试解决它,我有几个想法。嘿,阿里,下面的答案解决了你的问题吗?看起来你自己已经实现了SMIL。为什么不直接使用SMIL呢?老实说,我以前从未听说过SMIL(我只是一个程序员爱好者)。我很喜欢思考SVG路径背后的逻辑等,所以我就是这样处理的。我会看SMIL的,谢谢!我将向您介绍SMILThanks Robert,我现在也尝试了SMIL:)-
const target = document.querySelector("#target");
const animate_el = document.querySelector("#target > animate");
const from = animate_el.getAttribute("from");
const to = animate_el.getAttribute("to");
var d;

function forwards(){
  d = target.getAttribute("d");
  animate_el.setAttribute("from", d);
  animate_el.setAttribute("to", to);
  animate_el.beginElement();
}

function backwards(){
  d = target.getAttribute("d");
  animate_el.setAttribute("from", d);
  animate_el.setAttribute("to", from);
  animate_el.beginElement();
}

document.querySelector("#forwards").addEventListener('click', forwards);
document.querySelector("#backwards").addEventListener('click', backwards);
document.querySelector("#input_div > input").addEventListener('focus', forwards);
document.querySelector("#input_div > input").addEventListener('blur', backwards);