如何用程式設計師的方式,營造七夕氛圍感?

HMSCore發表於2021-08-13

一個“冷”知識,又雙叒叕到一年七夕了!

每年此時,送禮指南滿天飛,選擇困難症都給逼出來了,疑了個惑,能搞定愛情的人,卻在送禮這件事兒上糾結萬分!
要我說,七夕這種有情人的浪漫佳節,最重要的是圖一個氛圍!今天給大家介紹一個適合程式設計師的七夕“氛圍感十足”的小禮物——藉助華為影像服務,開發個超有愛七夕動圖,它支援輸入特殊關鍵詞,觸發“七夕”特效;同時,畫面還可跟隨指尖觸碰產生動效……效果先睹為快↓↓↓

Demo效果

有物件的秀給物件看,單身的朋友也可先做個七夕氛圍組成員,方法到手,也許下次就用上啦。

話不多說,開整!

開發步驟

1. 關鍵字動畫播放

第一步:素材準備

首先找到一個合適的圖片,這裡我們選擇了一張牛郎織女的圖片:

然後將其中有動畫效果的部件從圖中取出來。我們取出了雲朵,牛郎,織女,紅心四個元素。

第二步:整合準備

先按照下面的指導完成開發者註冊,建立應用,簽名配置:
https://developer.huawei.com/consumer/cn/doc/development/Media-Guides/config-agc-0000001050199019?ha_source=hms1

再按照如下方式進行程式碼倉和編譯依賴的配置:

  1. 在專案級“build.gradle”檔案中配置:
buildscript {
    repositories {
        google()
        jcenter()
        // 配置HMS Core SDK的Maven倉地址。
        maven {url 'https://developer.huawei.com/repo/'}
    }
    dependencies {
        ...
        // 增加agcp外掛配置。
        classpath 'com.huawei.agconnect:agcp:1.4.2.300'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        // 配置HMS Core SDK的Maven倉地址。
        maven {url 'https://developer.huawei.com/repo/'}
    }
}
  1. 在應用級“build.gradle”檔案配置編譯依賴(當前最新版本1.0.3.301):
dependencies { 
implementation 'com.huawei.hms:image-render: 1.0.3.301' 
  implementation 'com.huawei.hms:image-render-fallback: 1.0.3.301'
}
  1. 配置許可權

在“AndroidManifest.xml”檔案中配置應用所需許可權。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

第三步:功能開發

  1. 介面設計

這裡用最簡單的介面,一個FrameLayout中配置輸入框和按鈕:

我們將在這個FrameLayout中除錯和展現動畫。

  1. 配置儲存許可權申請

在MainActivity的onCreate()方法中,檢查是否擁有寫儲存的許可權,如果缺少,就呼叫requestPermission方法,對WRITE_EXTERNAL_STORAGE許可權進行申請:

int permissionCheck = ContextCompat.checkSelfPermission(ImageKitRenderDemoActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
initData();
initImageRender();
} else {
ActivityCompat.requestPermissions(ImageKitRenderDemoActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}

如果已有許可權,或許可權申請成功後,對Image渲染模組進行初始化

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // The permission is granted.
            initData();
            initImageRender();
        } else {
            // The permission is rejected.
            Log.w(TAG, "permission denied");
            Toast.makeText(ImageKitRenderDemoActivity.this, "Please grant the app the permission to read the SD card", Toast.LENGTH_SHORT).show();
        }
    }
}
  1. Image渲染模組初始化

獲取渲染例項,初始化,並獲取渲染檢視。 這裡會指定動畫元素的目錄:

ImageRender.getInstance(context, new ImageRender.RenderCallBack() {
        // 獲取場景動效服務例項成功回撥,返回場景動效服務例項
        @Override
        public void onSuccess(ImageRenderImpl imageRender) {
            imageRenderAPI = imageRender;
            if (imageRenderAPI != null) {
                int initResult = imageRenderAPI.doInit(sourcePath, Utils.getAuthJson());
                Log.i(TAG, "DoInit result == " + initResult);
                if (initResult == 0) {
                    // Obtain the rendered view.
                    RenderView renderView = imageRenderAPI.getRenderView();
                    if (renderView.getResultCode() == ResultCode.SUCCEED) {
                        View view = renderView.getView();
                        if (null != view) {
                            // Add the rendered view to the layout.
                            contentView.addView(view);
                            hashCode = String.valueOf(view.hashCode());
                        } else {
                            Log.w(TAG, "GetRenderView fail, view is null");
                        }
            }
        }
        // 獲取場景動效服務例項失敗回撥,返回錯誤碼
        @Override
        public void onFailure(int errorCode) {
        ...
        }
    });
  1. 配置關鍵字播放動畫

還記得前面留下的輸入框和按鈕嗎?我們使用關鍵字“Love”來進行動畫播放。只需要通過imageRenderAPI.playAnimation()即可觸發:

wordInput = findViewById(R.id.textinput);
enterBtn = findViewById(R.id.enter);
enterBtn.setOnClickListener(v -> {
    String inputContent = wordInput.getText().toString();
    if (inputContent.contentEquals("Love")) {
        if (null != imageRenderAPI) {
            imageRenderAPI. playAnimation();;
            wordInput.setVisibility(View.GONE);
            enterBtn.setVisibility(View.GONE);
        }
    } else {
        Toast.makeText(this,"再想想?",Toast.LENGTH_SHORT).show();
    }
});
  1. 配置動畫

框架搭好了,現在來到動畫的部分。Image Kit提供了5種基礎動效和9種高階動效,可以滿足絕大部分場景的使用要求。
在這裡我們使用到了透明度動畫,位移動畫,縮放動畫,以及下落動效。

Image Kit的動畫配置均在manifest.xml檔案中完成。可不要和AndroidManifest.xml檔案搞混了哦。

首先配置虛擬屏寬及背景圖片。配置虛擬屏寬之後,系統會根據不同的解析度對動畫進行縮放,使效果保持一致。

<Root screenWidth="1080">
<Image src="background.png"/>

我們希望牛郎織女能夠逐漸靠近直至相會,此時加入牛郎織女兩個元素,分別配置動線,此時使用到位移動畫的特效:

 <Image x="1000" y="1450" src="man.png">
       <PositionAnimation repeat="1">
           <Position x="0" y="0" time="0"/>
           <Position x="-450" y="-100" time="4000"/>
       </PositionAnimation>
    </Image>
    <Image x="-600" y="800" src="woman.png">
        <PositionAnimation repeat="1">
            <Position x="0" y="0" time="0"/>
            <Position x="700" y="300" time="4000"/>
        </PositionAnimation>
    </Image>

這樣牛郎織女將從螢幕兩側向中間靠近,直至相會。

相會之後在中心將出現跳動的紅心,這裡用到了透明度動畫及縮放動畫的疊加特效:

 <Image x="520" y="1350"  src="heart.png" visibility="#show1">
        <AlphaAnimation delay="4000" repeat="1">
            <Alpha a="255" time="0"/>
            <Alpha a="0" time="3000"/>
        </AlphaAnimation>
        <SizeAnimation delay="4000" repeat="1">
            <Size w="127" h="95" time="0"/>
            <Size w="508" h="380" time="3000"/>
        </SizeAnimation>
    </Image>

到現在,關鍵元素已經有了,可是看起來還是有點乾巴,要找點什麼點綴一下。
天上的雲朵也可以動起來,讓它在小範圍裡動一下更靈動一些:

 <Image x="150" y="200" src="cloud.png">
        <PositionAnimation repeat="0">
            <Position x="0" y="0" time="0"/>
            <Position x="-50" y="0" time="3000"/>
            <Position x="0" y="0" time="6000"/>
        </PositionAnimation>
    </Image>

想再羅曼蒂克一些,撒一些花瓣,這裡用到的就是下落動效:

 <DropPhysicalView gravityX="3" gravityY="10" airDensity="1000" delay="8800" visibility="#show2">
        <ItemGroup x="0" y="0" width="#screen_width" height="#screen_height">
            <Alpha x="0" y="#screen_height-1000" width="#screen_width" height="#screen_height" value="20"/>
            <Item count="20" src="follow.png">
                <Velocity isRandom="true" velocityX="0" velocityY="5"/>
                <Position isRandom="true"/>
                <AngleVelocity isRandom="true" angleVelocity="5"/>
                <Weight isRandom="true" value="0.5"/>
            </Item>
        </ItemGroup>
    </DropPhysicalView>
  1. 到這裡已經大功告成。最後可以再將動畫保留下來
// 開始錄製
int resultCode = imageRenderAPI.startRecord(json, new IStreamCallBack () {
    // 在錄製成功回撥中,將視訊或GIF位元組陣列儲存成mp4或GIF檔案
    @Override
    void onRecordSuccess(HashMap<String, Object> map) {
        ...
        String recordType = (String) hashMap.get("recordType");
        byte[] videoBytes = (byte[]) hashMap.get("videoBytes");
        byte[] gifBytes = (byte[]) hashMap.get("gifBytes");
        try {
            if (recordType.equals("1")) {
                if (videoBytes != null) {
                    // 儲存mp4檔案
                    saveFile(videoBytes, mp4Path);
                }
            } else if (recordType.equals("2")) {
                ...
            } else if (recordType.equals("3")) {
                ...
            }
        } catch (IOException e) {
            ...
        }
        ...
    }

    // 錄製失敗回撥
    @Override
    void onRecordFailure(HashMap<String, Object> map) {
        ...
    }

    // 錄製進度回撥,progress取值範圍為0-100
    @Override
    void onProgress(int progress) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                textProgress.setText("當前錄製進度:" + progress + "%");
            }
        });
    }
});

以上就得到最終效果啦~

除了動效之外,Image Kit還提供了濾鏡功能,可以給圖片添上浪漫的色彩,貼紙花字的功能,也可以給使用者的圖片增加愛情的元素。

瞭解更多>>

訪問華為影像服務官網

訪問華為開發者聯盟官網

獲取開發指導文件

華為移動服務開源倉庫地址:GitHubGitee

關注我們,第一時間瞭解** HMS Core **最新技術資訊~

相關文章